URL Decoder
Decode URL-encoded strings back to plain text using decodeURIComponent.
Click a card to auto-fill the input
What Is URL Decoding?
URL decoding is the reverse of URL encoding — it restores %XX percent-encoded sequences back to their original characters. It is especially useful when debugging APIs, analyzing logs, or cleaning up scraped data.
This tool uses the browser's native decodeURIComponent function, which correctly handles multi-byte UTF-8 sequences and restores Chinese and other non-ASCII characters.
How to Use
- Paste the URL-encoded string you want to decode into the left input box
- Click "Decode" — the restored plain-text string appears on the right
- Click "Copy Output" to copy the decoded result to your clipboard
Production Scenarios
Nginx, Apache, and Traefik access logs record request URIs in their encoded form. Decoding reveals the actual paths and parameters users accessed, making it much easier to spot anomalous traffic or track down the source of 404 errors.
Authorization servers (Auth0, Keycloak, WeChat Work) often return redirect_uri values with multiply-encoded state and code parameters. Decode layer by layer to verify parameter integrity and troubleshoot token-exchange failures or CSRF validation errors.
External links extracted from HTML pages, JS bundles, or API responses are often in encoded form. Decoding restores the real URLs for deduplication, classification, and storage. Be careful to distinguish URLs that were intentionally encoded in the source page from those your crawler framework auto-encoded.
Signature computation involves encoding parameters before hashing. Decode the encoded string from the request and compare it segment-by-segment against the expected signature base string to quickly find where a parameter value deviates. Often caused by sort-order logic that doesn't match the signing documentation.
Legacy data often mixes encoded and unencoded URLs, making display inconsistent. Batch-decode to unify the format, but be careful to preserve intentionally encoded URLs (e.g. pre-filled mailto links in emails). Don't blindly decode everything.
Common Mistakes
- Calling decodeURIComponent on non-UTF-8 encoded URLs — GBK-encoded Chinese uses different byte sequences (e.g. %D6%D0 instead of %E4%B8%AD). decodeURIComponent interprets everything as UTF-8 and produces garbled output. The fix: identify the source charset first; for non-UTF-8 data, use TextDecoder or a backend tool.
- Using decodeURIComponent on an entire URL — this decodes the :// ? & = structural characters as well, destroying the URL structure. For readable output, decode in segments: use decodeURI for path segments and decodeURIComponent for parameter values.
- Ignoring truncated % sequences — a trailing %E5 or %X without two hex digits throws URIError. Production code should validate with the regex %[0-9A-Fa-f] first, or return a friendly error inside try-catch.
- Failing to distinguish + from %20 — form encoding (URLSearchParams) decodes + as a space, but decodeURIComponent doesn't. If your URL-encoded string came from a form POST or legacy system and contains +, do .replace(/\+/g, '%20') before decoding.
Deep Dive: Engineering Details of URL Encoding/Decoding
encodeURI, encodeURIComponent, and the deprecated escape are not interchangeable. encodeURI treats the entire URL as one string and preserves structural characters like :/?#&=. encodeURIComponent treats the input as one component value and percent-encodes everything, including :/?#&=. Use encodeURI on a single param value and & or = will leak through and corrupt downstream parsing; use encodeURIComponent on the full URL and the whole URL loses its structure. General rule: always use encodeURIComponent on a single component (one param value or one path segment); leave full-URL handling to encodeURI or the URL/URLSearchParams API.
Browser encodeURIComponent deviates from RFC 3986. It leaves ! ' ( ) * unencoded, while strict RFC 3986 percent-encoding (e.g. the OAuth 1.0a signature base string) requires them encoded as %21 %27 %28 %29 %2A. Strict signing contexts therefore need a post-process: encodeURIComponent(s).replace(/[!'()*]/g, c => "%" + c.charCodeAt(0).toString(16).toUpperCase()). decodeURIComponent handles these percent-encoded forms transparently, so the decoding side needs no special treatment.
Detecting double encoding: if a string still contains %XX after one decodeURIComponent pass, you're likely looking at double-encoding — common with CDN forwarding, email tracking links, and gateway proxies. The production pattern is: loop decodeURIComponent until the result equals the previous iteration (cap at ~3 iterations to guard against malicious crafted inputs). But beware "legitimate % characters" — if the original data contains literal % (e.g., "100%", "3%5"), unbounded looping will corrupt it. The pragmatic rule: if you know the pipeline applies N layers of encoding, decode exactly N times instead of looping blindly.
Different URL components require different encoding strategies. Inside a path segment, / can stay unencoded (e.g., /api/v1/users/123), but inside a query value, & and = must be encoded (otherwise the next parser will split parameters incorrectly). Fragment (after #) accepts a wider character set and the browser performs no further encoding. Production code should split first with the URL object and handle each piece: new URL(rawUrl).searchParams.get(key) auto-decodes, sparing you the manual segmentation errors.