DEV Community

zhihu wu
zhihu wu

Posted on

Why Your API Calls Break: A Developer's Guide to URL Encoding

Why Your API Calls Break: A Developer's Guide to URL Encoding

URL encoding is one of those things that seems trivial until it isn't. You fire off an API call, the server returns a 400, and you stare at the URL wondering what went wrong. Nine times out of ten, the answer is encoding.

Here are the three URL encoding mistakes that cost developers hours of debugging — and how to fix them in 30 seconds.

1. The Double-Encoding Trap

This is the most insidious bug. You encode a URL once, pass it through a framework or middleware that encodes it again, and suddenly hello%20world becomes hello%2520world (the % got encoded to %25).

The symptom: Downstream services receive garbled data. OAuth callback URLs fail silently. API gateways forward corrupted parameters.

The fix: Before encoding, decode first to establish a clean baseline:

// Bad: might double-encode
const url = "https://api.example.com?q=" + encodeURIComponent(input);

// Good: decode first if input might already be encoded
const clean = decodeURIComponent(input); // throws if malformed
const url = "https://api.example.com?q=" + encodeURIComponent(clean);
Enter fullscreen mode Exit fullscreen mode

If you suspect double-encoding, look for %25 in your output — that's the smoking gun (% encoded as %25).

2. The + vs %20 Confusion

Both represent a space, but they're NOT interchangeable across contexts.

Context Encoding Works?
Query string (form data) +
Query string (manual) %20
Path segment + ❌ Broken
Fragment identifier + ❌ Broken
Everywhere %20 ✅ Always

The fix: Use %20 when you're not sure. It works universally. Use + only for application/x-www-form-urlencoded form submissions.

JavaScript's encodeURIComponent() outputs %20 — the safe choice. Python's urllib.parse.quote() does the same by default.

3. Encoding the Wrong Thing

The most common pattern I see in code reviews:

// Wrong: encodeURI on a full URL
const url = encodeURI("https://api.example.com/search?q=hello world");
// Result: "https://api.example.com/search?q=hello%20world" (works, but fragile)

// Wrong: encodeURIComponent on a full URL
const url = encodeURIComponent("https://api.example.com/search?q=hello world");
// Result: "https%3A%2F%2Fapi.example.com%2Fsearch%3Fq%3Dhello%20world" (broken)
Enter fullscreen mode Exit fullscreen mode

The rule: encodeURI() for entire URLs (preserves ://, ?, &, #). encodeURIComponent() for individual parameter values. Never mix them up.

Quick Debugging Workflow

When an API call fails with encoding issues, I use this 3-step process:

  1. Decode the URL to see what's actually there — strip away the percent-encoding and read the raw string
  2. Re-encode a clean version — start fresh from the decoded text
  3. Compare — if the re-encoded version works but the original doesn't, you had double-encoding or mixed encoding

I keep a free URL Encoder/Decoder bookmarked for exactly this: paste a broken URL, hit Decode, and instantly see what went wrong. No signup, no server uploads — everything runs in your browser.

🔗 Try it: codetoolbox.pro/tools/url-encoder.html

Modern Alternative: URLSearchParams

If you're writing modern JavaScript, the URL and URLSearchParams APIs handle encoding automatically:

const params = new URLSearchParams({ q: "hello world", page: "1" });
const url = "https://api.example.com/search?" + params.toString();
// "https://api.example.com/search?q=hello+world&page=1"
Enter fullscreen mode Exit fullscreen mode

This is cleaner, safer, and immune to double-encoding. Use it for new code.


What URL encoding bugs have burned you in production? Drop a comment — I'm collecting war stories.

Top comments (0)