Why JSON URLs Contain Backslashes (and How to Fix Them)
You call an API, open the response, and every link looks broken:
"image": "https:\/\/cdn.example.com\/photos\/cat.jpg"
Those backslashes look wrong, but the URL is perfectly fine. Here is what is actually happening.
The forward slash is being escaped
In JSON, the forward slash / is allowed to be written as \/. Both mean
exactly the same thing.
The specification permits escaping / so that strings containing </script>
can be safely embedded inside HTML without prematurely closing a script tag.
Many server frameworks — PHP’s json_encode is the usual culprit — do this by
default for every slash, whether or not the string is ever going near a script
tag.
So the URL is not broken?
Correct. When a JSON parser reads "https:\/\/cdn.example.com", it decodes it
back to https://cdn.example.com. The escaping exists only in the raw text;
once parsed, the value is an ordinary URL.
The trouble starts when you paste the raw string somewhere that does not run it through a JSON parser — a browser address bar, a shell command, a spreadsheet. That is when the stray backslashes actually break something.
Which escapes are actually required
\/ is the unusual one because it is entirely optional. The JSON specification
requires escaping for only three things:
- the double quote,
\" - the backslash itself,
\\ - control characters below U+0020 —
\n,\t,\r,\b,\f, or the generic\u00XXform
Everything else may be escaped, and a conforming parser must accept it. That
permission is what \/ relies on: "a/b" and "a\/b" decode to the same
string, and no parser is allowed to treat them differently.
So a response full of \/ is not a malformed response. It is a response from a
library that chose the maximally cautious option.
Why frameworks do it by default
The </script> case is the historical reason. If a server embeds JSON directly
into an HTML page:
<script>var data = {"html": "<\/script>"};</script>
an unescaped </script> inside the string would terminate the script block
early, breaking the page and opening an injection vector. Escaping every
forward slash makes that impossible without the encoder having to reason about
where its output will end up.
PHP’s json_encode escapes slashes unless you pass
JSON_UNESCAPED_SLASHES. Most other ecosystems — JavaScript’s
JSON.stringify, Python’s json.dumps, Go’s encoding/json — leave slashes
alone, which is why the same API can look different depending on what wrote it.
When it actually causes a bug
The escaping is harmless right up until something reads the raw text without parsing it. The realistic cases:
- Copying a URL out of a response viewer that shows raw JSON, then pasting it
into a browser or
curl. - Regex-matching URLs in the raw body — a pattern expecting
//silently skips every escaped URL, so they disappear rather than arriving broken. - Logs or diffs that store the raw payload, where
\/noise makes comparison harder than it needs to be.
In every one of those, the fix is the same: decode before you use it.
How to clean it
The fastest fix is to unescape the slashes before you copy the URL out:
- Open the API URL Extractor.
- Paste the API response into the JSON tab.
- Click Clean URLs to turn every
\/back into/. - Or click Extract URLs to pull out a clean, deduplicated list automatically.
No regex, no code, no copy-pasting into a console. Everything runs locally in your browser, so the response never leaves your machine — see browser-based developer tools for why that distinction is worth caring about with real API payloads.
Related reading
- How to extract all URLs from an API response
- Base64 encoding explained — a neighbouring case of “the string is fine, the encoding is confusing you”