%09 is a tab

%09 is a horizontal tab character — an invisible character that a browser deletes from a URL rather than encode.

Character(Tab)
NameTab
Encoded%09
ReservedNo

Why it breaks things

A tab, U+0009, lines up columns of text in a spreadsheet, a terminal or an editor. It has no job in a URL, and nobody types one into an address bar on purpose — it arrives by accident, usually pasted in from somewhere else.

The surprising part, verified in Node with new URL(): the WHATWG URL Standard does not encode a raw tab sitting inside a URL. It deletes it, during parsing, before the address is even split into parts. new URL("https://example.com/search?q=hello[TAB]world") returns the search string ?q=helloworld — the tab is gone completely, and the two words are joined with nothing between them.

That is worse than an encoding error for debugging. A %-encoded character at least leaves a trace. A tab pasted from a spreadsheet cell or a terminal just vanishes, silently turning "hello world" into "helloworld" with no error and no sign anything was there.

Real examples

Without encoding

https://example.com/users/42[TAB]/edit

With encoding

https://example.com/users/42%09/edit

[TAB] stands in for an actual tab character, which cannot be shown directly in this text. Pasted for real into a browser's address bar, that raw tab is deleted outright during parsing, leaving /users/42/edit — not an error, just a silently different path than the one that had the stray tab in it.

Without encoding

https://example.com/search?q=hello[TAB]world

With encoding

https://example.com/search?q=hello%09world

Verified with Node's new URL(): a raw tab here is deleted during parsing, producing ?q=helloworld with the two words joined and no space between them. Encoding it as %09 keeps the tab as a real, visible character in the value instead of letting it disappear.

Decode something

History

    Nothing yet.

    History stays in this browser. It is never sent to our server.

    Common questions

    Does a browser encode a tab in a URL as %09?
    Only if it is already encoded before parsing. A raw tab character sitting in a URL string is deleted outright by the WHATWG URL Standard during parsing, not converted to %09.
    Why did my pasted URL silently lose a tab character?
    Browsers and any WHATWG-compliant URL parser strip tab characters out of a URL during parsing. Nothing errors, and nothing shows where the tab used to be.
    Does this happen to values submitted through a web form?
    No, not in the same way. A value entered into a form field and submitted normally goes through URL-encoding, which turns a tab into %09 rather than deleting it. The deletion behaviour applies to a URL string that already contains a raw tab before it is parsed.
    How does a stray tab even end up in a URL?
    Usually from copying data out of a spreadsheet cell, a terminal, or code in an editor, where tabs are common, and pasting it into a URL or a form field without noticing.