{
  "schema_version": 2,
  "id": "develop/clients/connection-urls",
  "title": "Connection URLs",
  "url": "https://redis.io/docs/latest/develop/clients/connection-urls/",
  "summary": "Learn the Redis connection URL format and how each client library interprets it",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-10-12T14:48:04+01:00",
  "page_type": "content",
  "content_hash": "c83144f18294158d0b63577f9a30859efdf818f677350f0e2046d91a33b8de13",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Most Redis client libraries can connect using a URL such as\n`redis://default:<password>@<host>:6379/0`. Only the basic form of the URL\nmeans the same thing in every client. Everything else, including how you\nset timeouts, TLS options, and the RESP protocol version, is specific to\neach client library.\n\nThe `redis` and `rediss` URL schemes have a\n[provisional IANA registration](https://www.iana.org/assignments/uri-schemes/prov/redis),\nbut this is not a formal standard. The registration describes the basic form\nand says that query parameters are implementation-defined and not portable\nbetween clients."
    },
    {
      "id": "url-format",
      "title": "URL format",
      "role": "content",
      "text": "The basic form of a Redis URL is:\n\n[code example]\n\n| Part | Meaning | Default |\n| :-- | :-- | :-- |\n| `redis` or `rediss` | Use `redis` for a plain TCP connection and `rediss` for a TLS connection. | (required) |\n| `<username>` | Username for [ACL authentication](https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl). | `default` |\n| `<password>` | Password for authentication. | No authentication |\n| `<host>` | Hostname or IP address of the server. Enclose an IPv6 address in square brackets, for example `[::1]`. | `localhost` |\n| `<port>` | Port number of the server. | `6379` |\n| `<db-number>` | Number of the logical database to select. | `0` |"
    },
    {
      "id": "write-portable-urls",
      "title": "Write portable URLs",
      "role": "content",
      "text": "Follow these rules to write a URL that works the same way in every client\nthat accepts URLs:\n\n- **Use a lowercase scheme.** Lettuce, Predis, and synchronous redis-py\n  reject `REDIS://`, and ioredis only enables TLS for a lowercase `rediss://`.\n- **Always include the port.** Jedis rejects a URL without one.\n- **Always include the username with the password.** Write\n  `redis://default:<password>@<host>:6379` rather than leaving out the username.\n  The form `redis://:<password>@<host>` also means \"password only\" in every client.\n  However, the form `redis://<value>@<host>`, without a colon, is not portable:\n\n  | Client | `<value>` in `redis://<value>@<host>` means |\n  | :-- | :-- |\n  | redis-py, node-redis, ioredis, go-redis, redis-rs, Predis | Username, with no password |\n  | Lettuce, redis-rb | Password |\n  | Jedis | Error |\n\n- **Percent-encode special characters in the username and password.**\n  Encode any character that has a special meaning in URLs, such as `@`, `:`, `/`,\n  `?`, `#`, `%`, and `+`. For example, the password `p@ss:w+rd` becomes\n  `p%40ss%3Aw%2Brd`. See [Predis](#predis-php) and [redis-rb](#redis-rb-ruby)\n  for exceptions.\n- **Select the database with the path, not a query parameter.**\n  `redis://<host>:6379/2` selects database 2 in every client. The `?db=` query\n  parameter is ignored by some clients and has a different name in others.\n- **Don't put query parameters in a URL that more than one client reads.**\n  Clients recognize different parameter names, and they handle a name they\n  don't recognize differently:\n\n  | Behavior for an unknown query parameter | Clients |\n  | :-- | :-- |\n  | Ignored | node-redis, Jedis, Lettuce, redis-rs, redis-rb |\n  | Passed to the client as an option | redis-py, ioredis, Predis |\n  | Error | go-redis |\n\n- **Don't set the same option in both the URL and the client's options.**\n  Clients disagree about which one takes precedence.\n\nA URL often contains a password, so treat it as a secret. For example, keep it\nout of logs and error messages."
    },
    {
      "id": "client-support",
      "title": "Client support",
      "role": "content",
      "text": "The following table summarizes how each client library handles URLs. See the\nsections after the table for details.\n\n| Client | URL entry point | Schemes | Unix socket | Database in query | RESP version in query |\n| :-- | :-- | :-- | :-- | :-- | :-- |\n| [redis-py](#redis-py-python) | `redis.from_url()` | `redis`, `rediss`, `unix` | `unix:///<path>?db=<n>` | `?db=` | `?protocol=2` or `3` |\n| [node-redis](#node-redis-javascript) | `createClient({ url })` | `redis`, `rediss`, `unix` | `unix:///<path>?db=<n>` | Unix socket only | Not supported |\n| [ioredis](#ioredis-javascript) | `new Redis(url)` | `redis`, `rediss` | `/<path>?db=<n>` (no scheme) | `?db=` | Not supported |\n| [Jedis](#jedis-java) | `RedisClient.create(url)` | `redis`, `rediss` | Not supported | Not supported | `?protocol=2` or `3` |\n| [Lettuce](#lettuce-java) | `RedisURI.create(url)` | `redis`, `rediss`, `redis-socket`, `redis-sentinel`, `rediss-sentinel`, and others | `redis-socket:///<path>?database=<n>` | `?database=` or `?db=` | Not supported |\n| [go-redis](#go-redis-go) | `redis.ParseURL()` | `redis`, `rediss`, `unix` | `unix:///<path>?db=<n>` | `?db=` | `?protocol=2` or `3` |\n| [redis-rs](#redis-rs-rust) | `Client::open(url)` | `redis`, `rediss`, `unix`, `redis+unix` | `unix:///<path>?db=<n>` | Unix socket only | `?protocol=2` or `3` |\n| [redis-rb](#redis-rb-ruby) | `Redis.new(url: url)` | `redis`, `rediss`, `unix` | `unix:///<path>?db=<n>` | `?db=` | Not supported |\n| [Predis](#predis-php) | `new Predis\\Client(url)` | `redis`, `rediss`, `tcp`, `tls`, `unix` | `unix:///<path>?database=<n>` | `?database=` | `?protocol=3` |\n| [SE.Redis and NRedisStack](#stackexchangeredis-and-nredisstack-net) | Not supported | | | | |\n| [hiredis](#hiredis-c) | Not supported | | | | |\n\nThe `rediss` scheme turns on TLS, but most clients only let you configure\ncertificates in code. See the TLS section of each client's connection page,\nfor example\n[Connect to your production Redis with TLS](https://redis.io/docs/latest/develop/clients/redis-py/connect#connect-to-your-production-redis-with-tls)\nfor redis-py."
    },
    {
      "id": "redis-py-python",
      "title": "redis-py (Python)",
      "role": "content",
      "text": "Pass the URL to `redis.from_url()`, `Redis.from_url()`, or\n`ConnectionPool.from_url()`. The `redis.asyncio` module has the same functions.\n\n[code example]\n\n- Query parameters become keyword arguments for the connection. redis-py\n  converts the types of the parameters it recognizes, such as `socket_timeout`,\n  `socket_connect_timeout`, `health_check_interval`, `protocol`, and\n  `ssl_check_hostname`. It passes any other parameter as a string, and reports\n  an error for an unknown name when it creates the first connection.\n- Pass Boolean options that redis-py doesn't convert, such as\n  `decode_responses`, as keyword arguments rather than in the URL. For example,\n  `?decode_responses=False` passes the string `\"False\"`, which Python treats as\n  true.\n- A query parameter overrides the keyword argument with the same name.\n  If you specify both `?db=` and a path, `?db=` wins.\n- For TLS connections, you can set `ssl_cert_reqs` (`none`, `optional`, or\n  `required`) and `ssl_check_hostname` in the query.\n- `RedisCluster.from_url()` accepts only database 0 and doesn't support Unix\n  sockets. There is no URL form for Sentinel.\n\nSee the\n[`from_url()` reference](https://redis.readthedocs.io/en/stable/connections.html#redis.Redis.from_url)\nfor more information."
    },
    {
      "id": "node-redis-javascript",
      "title": "node-redis (JavaScript)",
      "role": "content",
      "text": "Pass the URL in the `url` option of `createClient()`:\n\n[code example]\n\n- node-redis ignores all query parameters in `redis://` and `rediss://` URLs.\n  Set other options, such as `RESP`, in the options object.\n- Values in the URL override the `username`, `password`, and `database`\n  options.\n- For a Unix socket, use `unix:///<path>`. You can add the database with\n  `?db=<n>`.\n- For a cluster, set `url` for each of the `rootNodes`. The credentials in\n  these URLs are only used for the initial connections, so set credentials for\n  the other nodes in the `defaults` option. There is no URL form for Sentinel."
    },
    {
      "id": "ioredis-javascript",
      "title": "ioredis (JavaScript)",
      "role": "content",
      "text": "Pass the URL as an argument to the `Redis` constructor:\n\n[code example]\n\n- ioredis doesn't reject other schemes. It adds `redis://` to the start of\n  any string that doesn't begin with `redis://` or `rediss://`, so a URL such as\n  `unix:///tmp/redis.sock` is read as a host named `unix`.\n- For a Unix socket, pass the socket path without a scheme, for example\n  `new Redis('/tmp/redis.sock?db=1')`.\n- ioredis passes query parameters to the client as options, with string\n  values. Set non-string options, such as `protocol`, in the options object\n  instead.\n- If you pass the URL before the options object, values in the URL take\n  precedence.\n- A `rediss://` URL for a cluster startup node doesn't turn on TLS. Set the\n  `tls` option in `redisOptions` instead."
    },
    {
      "id": "jedis-java",
      "title": "Jedis (Java)",
      "role": "content",
      "text": "Pass the URL to `RedisClient.create()`:\n\n[code example]\n\n- The URL must include a port.\n- For a password with no username, use `redis://:<password>@<host>:<port>`.\n  A URL such as `redis://<password>@<host>:<port>`, without a colon, is an error.\n- The only query parameter is `protocol`, with the value `2` or `3`.\n  Jedis ignores any other parameter, including `db`.\n- Don't add a slash after the database number. Jedis can't parse\n  `redis://<host>:6379/1/?protocol=3`.\n- There is no URL form for a Unix socket, a cluster, or Sentinel."
    },
    {
      "id": "lettuce-java",
      "title": "Lettuce (Java)",
      "role": "content",
      "text": "Pass the URL to `RedisURI.create()` or `RedisClient.create()`:\n\n[code example]\n\n- Lettuce recognizes these schemes:\n  - `redis` for TCP.\n  - `rediss` or `redis+ssl` for TLS, and `redis+tls` for TLS with STARTTLS.\n  - `redis-socket` or `redis+socket` for a Unix socket.\n  - `redis-sentinel` or `rediss-sentinel` for Sentinel.\n- Lettuce reads `redis://<password>@<host>`, without a colon, as a password.\n- Lettuce recognizes these query parameters:\n  - `timeout`: a number with an optional unit suffix, such as `10s`. With no\n    suffix, the unit is milliseconds.\n  - `database` or `db`: the database number. This takes precedence over the\n    path.\n  - `clientName`, `libraryName`, and `libraryVersion`.\n  - `verifyPeer`: `NONE`, `CA`, or `FULL`.\n  - `sentinelMasterId`: the master name, for Sentinel.\n- For Sentinel, list the Sentinel hosts separated by commas and name the\n  master, for example\n  `redis-sentinel://<password>@<host1>:26379,<host2>:26379/0?sentinelMasterId=mymaster`.\n  The password in the URL is for the data nodes, not the Sentinels.\n- For a cluster, pass `RedisClusterClient.create()` a URL with the seed nodes\n  separated by commas, for example `redis://<password>@<host1>:7000,<host2>:7001`.\n  Lettuce doesn't apply `clientName` or the database from this URL to the\n  cluster nodes.\n\nSee [URI syntax](https://redis.github.io/lettuce/user-guide/connecting-redis/)\nin the Lettuce documentation for more information."
    },
    {
      "id": "go-redis-go",
      "title": "go-redis (Go)",
      "role": "content",
      "text": "Parse the URL with `redis.ParseURL()` and pass the result to\n`redis.NewClient()`:\n\n[code example]\n\n- Query parameters set fields of `redis.Options`, using names in snake case\n  such as `dial_timeout`, `read_timeout`, `pool_size`, `client_name`, and\n  `protocol`. `ParseURL()` returns an error for any parameter it doesn't\n  recognize.\n- A duration parameter such as `dial_timeout` takes a number of seconds, such as\n  `5`, or a Go duration string, such as `500ms`.\n- For a `rediss` URL, `skip_verify=true` turns off certificate verification.\n  `skip_verify` is an error in a `redis` URL.\n- For a cluster, use `redis.ParseClusterURL()` and add the other seed nodes with\n  `addr=<host>:<port>` parameters. This function ignores the path and returns\n  an error for `db`.\n- For Sentinel, use `redis.ParseFailoverURL()`. The credentials in the URL are\n  for the Sentinels. Set the master name with `master_name=`, the master's\n  credentials with `username=` and `password=`, and other Sentinels with\n  `addr=`.\n\nSee the [`ParseURL()` reference](https://pkg.go.dev/github.com/redis/go-redis/v9#ParseURL)\nfor the full list of parameters."
    },
    {
      "id": "redis-rs-rust",
      "title": "redis-rs (Rust)",
      "role": "content",
      "text": "Pass the URL to `Client::open()`:\n\n[code example]\n\n- The URL must include a host.\n- The only query parameter for a TCP connection is `protocol`, with the value\n  `2`, `3`, `resp2`, or `resp3`. If you don't set it, redis-rs uses RESP2.\n- To skip certificate verification for a `rediss` URL, add the fragment\n  `#insecure` to the end of the URL. With the `tls-rustls` feature, this also\n  needs the `tls-rustls-insecure` feature.\n- For a Unix socket, use `unix:///<path>` or `redis+unix:///<path>`. Pass the\n  database and credentials as the `db`, `user`, and `pass` query parameters,\n  not in the address.\n- For a cluster, pass a URL for each node to `ClusterClient::new()`. The URLs\n  must all have the same credentials, protocol, and TLS mode.\n\nSee the [crate documentation](https://docs.rs/redis/latest/redis/) for more\ninformation."
    },
    {
      "id": "redis-rb-ruby",
      "title": "redis-rb (Ruby)",
      "role": "content",
      "text": "Pass the URL in the `url` option of `Redis.new`:\n\n[code example]\n\n- If you don't pass `url`, `host`, `port`, or `path`, redis-rb reads the URL from\n  the `REDIS_URL` environment variable.\n- Options that you pass to `Redis.new` take precedence over values in the URL.\n- The only query parameter is `db`. Set other options, such as `protocol`, in\n  `Redis.new`.\n- redis-rb reads `redis://<password>@<host>`, without a colon, as a password.\n- redis-rb decodes percent-encoding in the password, but not in the username.\n- For Sentinel, put the master name in place of the host and pass the\n  Sentinels in the `sentinels` option, for example\n  `Redis.new(url: 'redis://mymaster', sentinels: [...])`."
    },
    {
      "id": "predis-php",
      "title": "Predis (PHP)",
      "role": "content",
      "text": "Pass the URL to the `Predis\\Client` constructor:\n\n[code example]\n\n- Predis only reads the credentials and database from the address for the\n  `redis` and `rediss` schemes. For `tcp`, `tls`, and `unix`, use the\n  `username`, `password`, and `database` query parameters.\n- Predis doesn't decode percent-encoding in the username or password in the\n  address. If your password contains special characters, pass it as a\n  percent-encoded `password` query parameter instead.\n- The query parameter for the database is `database`, not `db`.\n- Predis passes all query parameters to the connection, for example\n  `timeout`, `read_write_timeout`, `persistent`, and `protocol`.\n- You can set TLS options with `ssl` parameters, for example\n  `?ssl[cafile]=<path-to-ca-file>&ssl[verify_peer]=1`."
    },
    {
      "id": "stackexchangeredis-and-nredisstack-net",
      "title": "StackExchange.Redis and NRedisStack (.NET)",
      "role": "content",
      "text": "StackExchange.Redis doesn't accept URLs. It uses its own configuration string\nformat, which is a comma-separated list of endpoints and `key=value` options.\nNRedisStack connects through StackExchange.Redis and uses the same format.\n\n[code example]\n\nIf you have a URL, convert it to a configuration string:\n\n| URL part | Configuration string |\n| :-- | :-- |\n| `rediss` scheme | `ssl=true` |\n| `<host>:<port>` | `<host>:<port>` |\n| `<username>` | `user=<username>` |\n| `<password>` | `password=<password>` |\n| `/<db-number>` | `defaultDatabase=<db-number>` |\n| `?protocol=3` | `protocol=resp3` |\n\nAlways include the port. If you set `ssl=true` and leave out the port,\nStackExchange.Redis uses port 6380, not 6379. Don't percent-encode the values.\nThe configuration string format has no way to escape a comma in a value.\n\nSee [Configuration](https://seredis.dev/Configuration) in the\nStackExchange.Redis documentation for the full list of options."
    },
    {
      "id": "hiredis-c",
      "title": "hiredis (C)",
      "role": "content",
      "text": "hiredis doesn't accept URLs. Pass the host and port to `redisConnect()`, or the\nsocket path to `redisConnectUnix()`. You can also use `redisConnectWithOptions()`\nwith a `redisOptions` struct. See [Connect](https://redis.io/docs/latest/develop/clients/hiredis/connect)\nfor examples."
    }
  ],
  "examples": [
    {
      "id": "url-format-ex0",
      "language": "plaintext",
      "code": "redis[s]://[[<username>][:<password>]@][<host>][:<port>][/<db-number>]",
      "section_id": "url-format"
    },
    {
      "id": "redis-py-python-ex0",
      "language": "python",
      "code": "import redis\n\nr = redis.from_url(\"rediss://default:<password>@<host>:6379/0?protocol=3\")",
      "section_id": "redis-py-python"
    },
    {
      "id": "node-redis-javascript-ex0",
      "language": "js",
      "code": "import { createClient } from 'redis';\n\nconst client = createClient({\n  url: 'rediss://default:<password>@<host>:6379/0'\n});",
      "section_id": "node-redis-javascript"
    },
    {
      "id": "ioredis-javascript-ex0",
      "language": "js",
      "code": "import Redis from 'ioredis';\n\nconst redis = new Redis('rediss://default:<password>@<host>:6379/0');",
      "section_id": "ioredis-javascript"
    },
    {
      "id": "jedis-java-ex0",
      "language": "java",
      "code": "RedisClient jedis = RedisClient.create(\"rediss://default:<password>@<host>:6379/0\");",
      "section_id": "jedis-java"
    },
    {
      "id": "lettuce-java-ex0",
      "language": "java",
      "code": "RedisClient client = RedisClient.create(\"rediss://default:<password>@<host>:6379/0\");",
      "section_id": "lettuce-java"
    },
    {
      "id": "go-redis-go-ex0",
      "language": "go",
      "code": "opt, err := redis.ParseURL(\"rediss://default:<password>@<host>:6379/0?protocol=3\")\nif err != nil {\n    panic(err)\n}\n\nclient := redis.NewClient(opt)",
      "section_id": "go-redis-go"
    },
    {
      "id": "redis-rs-rust-ex0",
      "language": "rust",
      "code": "let client = redis::Client::open(\"rediss://default:<password>@<host>:6379/0?protocol=3\")?;",
      "section_id": "redis-rs-rust"
    },
    {
      "id": "redis-rb-ruby-ex0",
      "language": "ruby",
      "code": "require 'redis'\n\nr = Redis.new(url: 'rediss://default:<password>@<host>:6379/0')",
      "section_id": "redis-rb-ruby"
    },
    {
      "id": "predis-php-ex0",
      "language": "php",
      "code": "$client = new Predis\\Client('rediss://default:<password>@<host>:6379/0');",
      "section_id": "predis-php"
    },
    {
      "id": "stackexchangeredis-and-nredisstack-net-ex0",
      "language": "csharp",
      "code": "ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(\n    \"<host>:6379,user=default,password=<password>,ssl=true,defaultDatabase=0\"\n);",
      "section_id": "stackexchangeredis-and-nredisstack-net"
    }
  ]
}
