Safeguard
Developer Tools•

Why does my database password with an @ sign break the URL?

Characters like @, / and : have meaning in a connection URL. Percent-encode the password or pass it as a separate parameter so the driver reads it.

Safeguard Security Team
4 min read

Because @, /, : and a few other characters have a job inside a URL, a password that contains them gets misread. Percent-encode the password, for example @ becomes %40 and / becomes %2F, or pass the password as a separate parameter instead of embedding it in a connection string.

What goes wrong

A connection URL has the shape scheme, user, password, host, port, database. The parser finds the password by looking for delimiters. An @ sign marks the end of the credentials and the start of the host. If your password contains an @, the parser stops reading the password early and treats the rest as a host name. The error you see is usually about an unknown host or a failed login, which sends people looking in the wrong place.

The SQLAlchemy documentation has a section on exactly this. It says special characters used in the user and password need to be URL encoded to be parsed correctly, including the @ sign. Its example turns a password containing an at sign and a slash into one using %40 and %2F.

Which characters to encode

RFC 3986 defines the reserved characters that act as delimiters. The general delimiters are the colon, slash, question mark, hash, square brackets and the at sign. It also lists sub delimiters such as ampersand, plus, equals and comma. If data collides with one of these, it must be percent encoded before the URI is formed.

CharacterEncoded
@%40
/%2F
:%3A
?%3F
#%23
%%25

The PostgreSQL client library documentation says the same about its own URIs: the connection URI needs to be encoded with percent encoding if it includes symbols with special meaning in any of its parts.

Two ways to fix it

  1. Encode the password with a library function in your language before building the URL. Do not hand encode in a script you will forget about.
  2. Use separate fields. Most drivers accept host, user, password and database as separate parameters, or as key value pairs in a keyword style connection string. Then nothing needs encoding.

SQLAlchemy offers a programmatic way to build a URL so the password is handled as a value. Its documentation lists creating URLs programmatically as a supported approach.

Do not paste the failing string anywhere

When a connection fails, the instinct is to paste the full string into a chat, a ticket or a log. That string contains the password. Before you share an error, remove the credentials. Check whether your driver prints the URL in its error message, and redact if so. Our post on what never to log covers the habit.

Pick a simpler password too

Some teams avoid the problem by generating passwords from letters and digits only. A long random value of that kind avoids encoding bugs and is not weaker if it has enough length. Whichever you choose, store it in a secret manager, not in a file in the repository. See environment variables for secrets for where those values can leak.

A quick test

Write a short test that builds your connection string from a password containing every character in the table above, then connects. Run it in CI against a throwaway database. It catches both an encoding bug and a rotation that introduces a new special character.

Safeguard scans dependencies, including database drivers, and can find secrets patterns in repositories as part of its checks. A free scan is at gold.safeguard.sh/scan.

Quick check

Is %40 the same as @ to the database?

Yes, after the driver decodes the URL. It is the encoded form of the at sign.

Do I encode the whole URL?

No. Encode the parts that contain special characters, such as the user and password.

Is a keyword style string safer than a URL?

It avoids the delimiter problem for the password, though it can still leak if logged.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.