URL Encoder & Decoder Guide: Percent-Encoding Explained

TK
Toolshubkit Editor
Published Nov 2024
7 MIN READ • Developer Utilities
Special characters in URLs can silently break parsers, corrupt query parameters, and open security vulnerabilities. Our URL Encoder & Decoder applies RFC 3986 percent-encoding to any text and decodes encoded strings back to readable form — entirely in your browser.

Technical Mastery Overview

Safe encoding
Real-time result
RFC Compliant
Local Sandbox

Why URLs Need Encoding

URLs are restricted to a specific set of characters. The RFC 3986 specification defines two categories:

Unreserved characters — safe anywhere in a URL, no encoding needed:

A–Z  a–z  0–9  -  _  .  ~

Reserved characters — have structural meaning in URLs and must be encoded when used as data:

:  /  ?  #  [  ]  @  !  $  &  '  (  )  *  +  ,  ;  =

Everything else — spaces, accented characters, emoji, brackets, quotes — must be percent-encoded.

How Percent-Encoding Works

Each byte of the character is represented as %XX where XX is the hexadecimal value:

Character UTF-8 bytes Encoded
Space 0x20 %20
& 0x26 %26
= 0x3D %3D
# 0x23 %23
+ 0x2B %2B
é 0xC3 0xA9 %C3%A9
😊 0xF0 0x9F 0x98 0x8A %F0%9F%98%8A

Multi-byte UTF-8 characters produce multiple percent-encoded pairs — that's why emoji can take 12+ characters when encoded.

The Most Common Bug: Unencoded Query Parameters

https://api.example.com/search?q=hello world&filter=type=user&sort=date

This URL has three problems:

  1. Space in hello world — breaks the URL at the space
  2. = inside the filter value — looks like a new key-value pair
  3. & separating filter value from sort — splits the parameter mid-value

Correctly encoded:

https://api.example.com/search?q=hello%20world&filter=type%3Duser&sort=date

Now the parser correctly reads:

  • q = hello world
  • filter = type=user
  • sort = date

encodeURIComponent vs encodeURI — Know the Difference

JavaScript has two encoding functions and confusing them is a very common mistake:

encodeURI("https://example.com/path?q=hello world&x=a=b")
// → "https://example.com/path?q=hello%20world&x=a=b"
// Encodes spaces but NOT :, /, ?, &, = — they're structural to the URL

encodeURIComponent("hello world&x=a=b")
// → "hello%20world%26x%3Da%3Db"
// Encodes EVERYTHING including &, =, /, ? — treats input as a raw value

Rule: use encodeURIComponent for individual parameter values, encodeURI for full URLs you want to escape just enough for safe transmission.

// Build a search URL correctly
const query = "C++ programming & algorithms";
const url = `https://api.example.com/search?q=${encodeURIComponent(query)}`;
// → "https://api.example.com/search?q=C%2B%2B%20programming%20%26%20algorithms"

The + vs %20 Space Ambiguity

Two different encodings for spaces exist:

  • %20 — standard percent-encoding, works everywhere
  • + — only valid in application/x-www-form-urlencoded (HTML form submissions)

HTML forms use + for spaces; URLs use %20. Mixing them causes bugs:

// In a URL query string: %20 is correct
const url = `https://example.com/search?q=hello%20world`;

// In a form body: + is conventional (and what browsers send)
// application/x-www-form-urlencoded: q=hello+world

When you see + in a URL and decode it with decodeURIComponent, the + is NOT converted to a space — only %20 is. Use decodeURIComponent(str.replace(/\+/g, ' ')) when decoding form-encoded strings.

Encoding for Different URL Positions

Different parts of a URL have different encoding requirements:

URL part What to encode Function
Full URL Minimal (just spaces and illegal chars) encodeURI()
Query parameter value Everything reserved encodeURIComponent()
Path segment Everything except / separators Custom or libraries
Fragment (#...) Reserved chars encodeURIComponent()
Username / password Reserved chars encodeURIComponent()

Our encoder applies the correct encoding for query parameter values — the most common use case.

Decoding — Reading Encoded URLs

When you receive an encoded URL (from a webhook, a log entry, an OAuth callback), decoding it reveals the original parameters:

/callback?code=4%2F0AfJohXl7g&state=abc%3D123&error=access_denied
  ↓ decode ↓
/callback?code=4/0AfJohXl7g&state=abc=123&error=access_denied

Decode any encoded URL with our tool to read it clearly. Useful when:

  • Debugging OAuth callback URLs
  • Reading webhook target_url values from API responses
  • Interpreting log entries with encoded URLs
  • Understanding redirect chains

Security: Open Redirects and Encoding Attacks

Improper URL handling creates security vulnerabilities:

Open redirect via encoding

https://app.example.com/redirect?url=https://evil.com
// vs
https://app.example.com/redirect?url=https%3A%2F%2Fevil.com

If your server decodes the url parameter and redirects without validation, both forms can redirect to evil.com. Always validate redirect destinations against an allowlist, regardless of encoding.

Path traversal via double-encoding

/files/..%2F..%2Fetc%2Fpasswd

Some servers decode this to /files/../../etc/passwd and serve sensitive files. Always normalize and validate paths after decoding, not before.

Building API Request URLs

When constructing URLs for our cURL Generator, encode each query parameter value separately before concatenating:

# Build URL with encoded parameters
QUERY=$(python3 -c "import urllib.parse; print(urllib.parse.quote('user@example.com'))")
curl "https://api.example.com/users?email=$QUERY"

Or let the HTTP library handle it:

const params = new URLSearchParams({
    email: 'user@example.com',
    role: 'admin & manager'
});
fetch(`/api/users?${params}`);
// Automatically encodes → /api/users?email=user%40example.com&role=admin+%26+manager

URLSearchParams uses + for spaces (form encoding convention) — if your API expects %20, convert after: .toString().replace(/\+/g, '%20').

Experience it now.

Use the professional-grade URL Encoder/Decoder with zero latency and 100% privacy in your browser.

Launch URL Encoder/Decoder
URL encoding is a small thing that breaks big systems when ignored. Always encode user-provided values before embedding them in URLs, and know which function to use for which context.