XML URL Encoding

Drop XML into a query string without the angle brackets, ampersands, and line breaks tearing the URL apart. Encode with the escaping rule your endpoint expects, decode a string someone sent you, and see how much of the 2,000 character budget is left before a proxy rejects the request.

XML in

source

Percent-encoded out

result

Paste something above, or load one of the samples.

0Characters
0Bytes
0Escapes
0%Size change
0%URL budget

Comfortably inside the 2,000 character line most servers hold to.

Request preview

Load a sample

Ten characters in XML break a URL

XML markup is built from the same characters a URL reserves for structure. An angle bracket opens a tag in one and confuses proxies in the other. An ampersand separates a child entity in one and starts a new query parameter in the other. Send raw XML through a query string and the server reads the first fragment, then treats everything after the first & as a different field.

CharacterEscapeWhat happens when it stays raw
&%26Starts a new query parameter. Half your document lands in a field the endpoint never reads.
=%3DSplits a key from a value. An attribute assignment turns into a parameter boundary.
#%23Starts the fragment. Everything after it stays in the browser and never reaches the server.
%%25Opens an escape sequence. A literal percent leaves a malformed pair the decoder throws on.
<>%3C%3EForbidden in a URI by RFC 3986. Proxies, WAFs, and log parsers rewrite or reject them.
"%22Closes the quoted attribute when the URL is written into an HTML link.
space%20Ends the request line as far as older servers are concerned. Indented XML is mostly spaces.
+%2BReads as a space in form-encoded values, so a plus sign in your data silently disappears.
line break%0A%0DA raw CR LF inside a request line is the request-splitting pattern. Servers drop the request.

Percent encoding replaces each of these with a percent sign and the hex value of the byte. Nothing about the XML changes. The bytes travel through the URL layer intact, and whatever sits on the other end decodes them back before parsing.

Three escaping rules, three different outputs

The Escaping control picks how aggressive the encoder gets. The same fragment produces three results, and picking the wrong one is the most common reason a request arrives mangled.

Query valueencodeURIComponent
%3Cnote%20a%3D%221%22%3E
x%20%26%20y%3C%2Fnote%3E
Form fieldform-urlencoded
%3Cnote+a%3D%221%22%3E
x+%26+y%3C%2Fnote%3E
Whole URIencodeURI
%3Cnote%20a=%221%22%3E
x%20&%20y%3C/note%3E

Query value escapes every reserved character, including &, =, /, and ?. Use it whenever the XML sits inside one parameter. This is the setting you want almost every time.

Form field does the same work, then writes spaces as + instead of %20. That rule comes from HTML form submission, not from the URI specification. Some frameworks decode + as a space everywhere, some only in a POST body. Pick this when you are building a body with Content-Type: application/x-www-form-urlencoded.

Whole URI leaves the delimiters alone, so &, =, /, and # pass through untouched. Look at the third card above. The ampersand from x & y survives, which means the endpoint sees a new parameter starting mid-document. This setting exists for escaping a URL that is already assembled, not for escaping data going into one. Use it on a finished address, never on XML.

The Strict RFC 3986 box adds the six characters JavaScript leaves behind: !, ', (, ), and *. They are legal in a URL, so most endpoints never notice. AWS request signing, OAuth 1.0 signature bases, and a few payment gateways compute their hash over the strict form, so an unescaped apostrophe there produces a signature mismatch with no useful error message.

XML entities and percent encoding sit on different layers

Both look like escaping. They solve different problems, and mixing them is where the confusing bugs live.

An XML entity such as &amp; or &lt; belongs to the document. The XML parser resolves it. Percent encoding belongs to the transport. The HTTP stack resolves it. Load the Ampersands and entities sample and watch what happens to Smith &amp; Sons. The ampersand of the entity becomes %26, so the encoded string holds %26amp%3B. Decoding restores &amp;, the parser turns that into a literal ampersand, and the buyer name comes out right.

The failure mode is unescaping twice. Some code decodes the URL, sees text containing &lt;, and runs an HTML entity decoder over it for safety. Now a customer note reading &lt;script&gt; has become a real tag, and the document either fails to parse or carries markup nobody intended. Decode the transport layer once, hand the bytes to the XML parser, and let the parser resolve the entities.

Double encoding, and how to recognise it

Encoding an already-encoded string turns every % into %25. The result looks plausible and travels fine. It breaks quietly at the far end, where the parser receives literal text like %3Cconfig%3E rather than markup.

Encoded oncecorrect
%3Cconfig%3E%3Cmode%3E
live%3C%2Fmode%3E
Encoded twicebroken
%253Cconfig%253E%253Cmode
%253Elive%253C%252Fmode%253E

The tell is %25 followed by two more hex digits. Decoding flags it here rather than handing back a half-readable string. Load the Encoded twice sample, press Decode, and the status line says the output still holds escapes. Decode again to reach the XML.

Double encoding usually comes from a client library that already escapes parameters. Building the query string by hand and then passing it to a helper such as requests in Python or URLSearchParams in the browser applies the second pass. Give those libraries the raw XML string and let them escape it once.

The 2,000 character line

HTTP itself sets no maximum URL length. Every implementation between you and the endpoint sets one anyway, and the smallest number in the chain wins.

The URL budget meter measures against 2,000 characters, because that is the point below which nothing in the usual chain complains. Percent encoding roughly triples the length of tag-heavy XML, since every angle bracket costs three characters instead of one. A 700 byte SOAP envelope lands near the limit on its own.

Collapse whitespace between tags is ticked by default for that reason. Indentation carries no meaning between elements, and stripping it from a pretty-printed document removes a third of the length before encoding starts. Text inside an element stays untouched, so values keep their spacing.

Past 2,000 characters, stop encoding and change the request. A document too big for a query string is telling you it belongs in a POST body with Content-Type: application/xml, where no escaping happens at all. Query strings also land in server access logs, browser history, proxy caches, and the Referer header of the next request. XML holding customer records, tokens, or medical data does not belong in a URL at any length.

What the checks tell you

Every encode runs the source through the browser DOM parser first. A well-formedness failure does not block the encoding, because escaping a broken fragment is a reasonable thing to want. The status line says so instead, which saves the round trip of discovering it after the request returns a 400.

Decoding runs two checks of its own. A stray % without two hex digits behind it reports the exact position, since a missing %25 is the usual cause. A sequence such as %C0 or %E2%28 is valid hex but not valid UTF-8, which throws in every decoder including the one behind your endpoint. Both come back as a message rather than an empty box.

Unicode passes through as UTF-8 bytes. Load the Accents and emoji sample and the character count stays close to the source while the byte count jumps, because รถ costs two bytes and an emoji costs four. The byte figure is what a server counts against its limits.

Where this page stops

There is no compression step. Percent encoding grows a document, never shrinks one. Teams pushing large XML through a URL usually gzip the bytes and Base64 the result first, which needs matching code on both ends. The XML to Base64 page covers half of that.

Validation stops at well-formedness. Whether your document matches its XSD or WSDL contract is a separate question, and a schema check belongs before the encoding step rather than after it.

Nothing here splits a document across several parameters. Some APIs accept doc1, doc2, and so on, reassembled server side. That scheme has to be agreed with the endpoint, so building it is your side of the work.

Everything runs in this tab. The XML never reaches a server, which is what makes the page usable with a payload from production. Nothing survives closing the tab, so save what you need.

Nearby pages

For plain text rather than markup, the URL encoder skips the XML checks. When the document needs to travel in a header or a JSON string instead of a URL, XML to Base64 is the usual choice. If the XML refuses to parse before you get this far, XML parser reports the line and column, and XML pretty print re-indents a document flattened by the collapse option. A SOAP response that came back from the endpoint is easier to read through SOAP to JSON.

Questions that come up mid-request

The things people hit once a real document is in the box.

Which escaping setting should I pick?

Query value, in almost every case. It escapes the delimiters that break a query string, including the ampersand and equals sign that appear throughout XML markup. Pick Form field only when you are building a request body typed as application/x-www-form-urlencoded. Whole URI leaves delimiters raw, so it belongs on a finished address rather than on data going into one.

Why is my encoded XML three times longer than the source?

Each reserved character becomes three characters. Angle brackets, quotes, spaces, and equals signs make up a large share of any XML document, so tripling is normal for markup-heavy input. Collapsing whitespace between tags recovers part of it. Past 2,000 characters, move the document into a POST body instead.

My output starts with %253C instead of %3C. What went wrong?

The string was encoded twice. The second pass turned every percent sign into %25. Decode it once to get back to the single-encoded form, then decode again for the XML. The usual cause is escaping the value by hand and then passing it to an HTTP client that escapes parameters for you.

Does percent encoding replace XML entities like &amp;?

No. They work at different layers. Entities belong to the document and the XML parser resolves them. Percent encoding belongs to the transport and the HTTP stack resolves it. An entity written as &amp; comes out of the encoder as %26amp%3B and arrives intact.

Why does the decoder say my string is not valid UTF-8?

A sequence such as %C0 or %E2%28 is valid hexadecimal but does not describe a real UTF-8 character. Every standard decoder rejects it, including the one at your endpoint. The usual cause is a string encoded as Latin-1 or truncated in the middle of a multi-byte character.

Should I use %20 or a plus sign for spaces?

Use %20 in a query string. It is correct everywhere, including path segments where a plus sign stays a literal plus. The plus form comes from HTML form submission and is safe in a form-urlencoded body. Mixing them is how a plus sign in your data quietly turns into a space.

Is the XML uploaded anywhere?

No. Encoding, decoding, and the well-formedness check all run in JavaScript inside this tab. The document stays in browser memory and disappears when the tab closes. That said, a URL built from sensitive XML still ends up in access logs and browser history once you send it.

What is the Strict RFC 3986 option for?

It escapes the exclamation mark, apostrophe, parentheses, and asterisk that the browser encoder leaves alone. Ordinary endpoints treat both forms the same. Signed requests do not, so AWS Signature Version 4, OAuth 1.0, and some payment gateways need the strict form or the signature will not match.