Article · Mar 23, 2026 · 7 min read

URL encoding for REST APIs

REST APIs put data in URLs in three places: path segments, query parameters, and (sometimes) URL-encoded request bodies. Each has different encoding requirements, and getting them right is the difference between a working integration and a debugging session.

This article covers the three contexts, common framework behaviors, and the edge cases that trip up real-world REST clients.

The three URL contexts in a REST API

1. Path segments/users/{id}/orders/{orderId}

The {id} and {orderId} need URL encoding when they contain anything beyond letters and digits. Use RFC 3986 strict (space → %20).

2. Query parameters?q=value&page=2

Each value needs encoding. Most APIs accept both form-encoded (+ for space) and strict (%20) — but strict is safer.

3. Form-encoded request bodyname=John&message=Hello

Same encoding as query parameters, but in the request body with Content-Type: application/x-www-form-urlencoded.

Path segment encoding

The most error-prone of the three. Path segments must encode:

// User ID is a UUID
GET /users/550e8400-e29b-41d4-a716-446655440000   ← fine, no encoding needed

// User ID has a slash (unusual but possible)
GET /users/A%2FB                                  ← encoded
// Decoded interpretation: user ID is literally "A/B"

The %2F-in-path landmine

Many servers reject %2F in path components by default. The default Apache configuration treats encoded slashes as a path-traversal attack and returns 404 or 400.

Workaround on Apache: Set AllowEncodedSlashes On in the server config.

Workaround on Nginx: Custom location matching with regex (no clean built-in option).

Best practice: Avoid putting data with potential / characters in path segments. Use a query parameter instead, where encoded slashes are universally accepted.

Query parameter encoding for filters and search

The common REST pattern of ?filter=value&sort=name:

// Simple values
GET /products?q=laptop&category=electronics

// With special chars
GET /products?q=rock%20%26%20roll&category=music
// Decoded: q="rock & roll", category="music"

If you don’t encode the & in rock & roll, the parser sees:

?q=rock 
&roll=  ← interpreted as separate parameter with empty value
&category=music

Always encode each value before concatenating.

API-specific conventions

GitHub API: strict, returns 400 on bad encoding

// Search repositories
GET /search/repositories?q=hello+world+language:python
// + as space works
// Special chars in query: must be percent-encoded
GET /search/repositories?q=%2Bhello%20%22world%22

Stripe API: form-encoded bodies

POST /v1/customers
Content-Type: application/x-www-form-urlencoded

name=Jenny%20Rosen&email=jenny%40example.com

Stripe’s POST endpoints accept form-encoded bodies, not JSON. The encoding is standard URL encoding.

AWS API Gateway: strict path encoding

AWS expects RFC 3986 strict for path segments. Spaces must be %20, not +. Hex must be uppercase.

OpenStreetMap Overpass API: complex query encoding

The Overpass API takes its own query language as a URL parameter. The whole query must be URL-encoded, including special characters that are syntax in the query language itself.

Building REST API URLs in real code

Node.js

const url = new URL('https://api.example.com/users/' + encodeURIComponent(userId));
url.searchParams.set('include', 'orders,profile');
url.searchParams.set('limit', '50');
fetch(url.toString());

Python (requests library)

import requests
from urllib.parse import quote

response = requests.get(
    f'https://api.example.com/users/{quote(user_id, safe="")}',
    params={'include': 'orders,profile', 'limit': 50}
)
# requests auto-encodes params dict

cURL

# GET with query params
curl --data-urlencode "q=hello world" \
     --data-urlencode "filter=type:premium" \
     -G https://api.example.com/search

# POST with form-encoded body
curl -X POST https://api.example.com/users \
     --data-urlencode "name=Jenny Rosen" \
     --data-urlencode "email=jenny@example.com"

Embedding URLs as parameter values

Webhook URLs, OAuth callbacks, and redirect parameters often contain entire URLs as values. The inner URL must be fully URL-encoded:

// Setting up an OAuth callback
const callbackUrl = 'https://myapp.com/auth/callback?ref=oauth_v2';
const authUrl = `https://accounts.example.com/authorize?redirect_uri=${encodeURIComponent(callbackUrl)}&client_id=abc123`;
// → ?redirect_uri=https%3A%2F%2Fmyapp.com%2Fauth%2Fcallback%3Fref%3Doauth_v2&client_id=abc123

The inner URL’s :, /, ?, & all need encoding so the outer URL parser doesn’t misinterpret them.

Common REST encoding mistakes

1. Encoding the entire URL instead of just values

// Wrong
const url = encodeURIComponent('https://api.example.com/users?id=123');
// "https%3A%2F%2Fapi.example.com%2Fusers%3Fid%3D123"
// → No longer a URL

2. Mixing path and query encoding styles

// Wrong: + in a path means literal +
const userId = encodeURIComponent('John Doe').replace(/%20/g, '+');
GET /users/John+Doe  // → looking for user named "John+Doe" literally

3. Forgetting to encode commas in arrays

// Some APIs use commas as multi-value separator
GET /search?fields=id,name,email   ← if the field names are guaranteed clean, fine

// But user-provided values must encode commas
GET /search?names=Smith%2C+John&Jones%2C+Mary
// "Smith, John" + "Jones, Mary" — without encoded commas, server sees four names

4. Sending JSON values without proper escaping

Some APIs accept JSON-encoded values in URL parameters. The JSON itself must be properly escaped before URL-encoding:

const filter = { status: "active", tier: "premium" };
const jsonStr = JSON.stringify(filter);
// '{"status":"active","tier":"premium"}'

const param = encodeURIComponent(jsonStr);
// "%7B%22status%22%3A%22active%22%2C%22tier%22%3A%22premium%22%7D"

const url = `/search?filter=${param}`;

Debugging a REST API encoding issue

Step 1: Capture the actual HTTP request. Use browser DevTools, Postman, or curl -v. Note the exact path and query string sent.

Step 2: Decode the URL. Paste it into our URL decoder and check if the decoded form matches what you intended.

Step 3: Check the server’s docs for encoding conventions. Some APIs explicitly require uppercase hex (%2C not %2c), some require strict path encoding (no + for space).

Step 4: Re-encode with the right tool. If you’re working in JavaScript, prefer the URL constructor and URLSearchParams over manual concatenation — they handle the edge cases.

Bottom line

Three rules cover most cases:

  1. Encode each value separately, never the whole URL.
  2. Use %20 for spaces in path segments; either %20 or + for query strings is fine.
  3. Use your language’s standard library (URL+URLSearchParams in JS, urllib.parse in Python, etc.) instead of manual string concatenation.

Found this useful? Try the URL decoder, the URL encoder, or browse all tools.

More reading

From the blog.