Raw HTTP Message Inspector

Paste the raw text a browser and a server send each other and see it pulled apart and checked. Content-Length counts bytes, not characters, and a message carrying both a length and a chunked encoding is the basis of request smuggling — both are checked here.

How to use it

Paste either half of the conversation, a request or a response, and it is read the way a server reads it: start line first, then every header including the ones that turn up twice.

  1. Paste the whole message Everything from the start line down to the end of the body, headers included. A copy out of a proxy, a curl trace or a log is exactly the right thing. Requests and responses are both understood, and which one you pasted is worked out for you.
  2. Read the framing first Before anything else, check how the message says its body ends. That one decision is what a server acts on, and it is where the faults that waste an afternoon live.
  3. Compare the length with the bytes The body is measured in UTF-8 bytes and set against what Content-Length claims. If they differ, that is your bug, and the number shown is the one to write.
Full instructions

The message

paste it from a proxy, a terminal or a log, or open a saved file

What it says

In depth

Reading a raw HTTP message the way a server reads it

What a raw HTTP message looks like, why the byte count matters more than the character count, every part of the inspector explained, a worked example with a request that hangs, the framing traps that waste whole afternoons, and why pasting a captured message here is the safe place to do it.

Screenshot: The two mistakes that make a message hang
The two mistakes that make a message hang as it appears when the page opens.

The text behind every web request

Every time a browser loads a page, it sends a block of text to the server. That block starts with a line naming the method and the path, followed by a set of headers, then a blank line, and then the body. The server reads this text in order, decides what was asked for, and sends back a block of text in the same format with a status line at the top.

Most developers never see this raw text. Their framework handles it, and the browser's network panel shows a tidy summary. But when something breaks at the wire level, a tidy summary is not enough. A request that hangs, a response that truncates, or a proxy that rewrites headers all require looking at the actual bytes.

That is what this inspector does. Paste the raw text of a request or response and it takes it apart piece by piece, the same way a server would. It reports the start line, every header, how the body is framed, and the body itself with any chunked encoding undone.

Who pastes raw messages into a tool like this

Backend developers debugging a failing API call are the most common users. They capture a request from a proxy like Fiddler or mitmproxy, or from a curl trace, and need to see exactly what was sent.

Security researchers inspecting traffic for request smuggling vulnerabilities need to verify that Content-Length and Transfer-Encoding do not conflict. That conflict is the basis of an entire class of attacks, and spotting it by eye in a wall of text is error-prone.

DevOps engineers reading server logs often find requests printed in their raw form. Pasting one into the inspector is faster than counting bytes and parsing chunk sizes by hand.

  • Verifying that Content-Length matches the actual number of bytes in the body.
  • Decoding a chunked Transfer-Encoding to see the reassembled body.
  • Checking whether line endings are proper CRLF or just bare line feeds.
  • Finding headers that appear twice when they should not, like a duplicate Host or Content-Length.
  • Understanding why a hand-written request never gets a response.

The input pane and what to paste

The left pane is labelled The message, with a hint that reads paste it from a proxy, a terminal or a log, or open a saved file. Paste the full message starting from the very first line. For a request, that is the method line, such as GET /orders HTTP/1.1. For a response, that is the status line, such as HTTP/1.1 200 OK.

Include every header line and the blank line that separates headers from the body. If there is a body, include that too. The tool figures out on its own whether you pasted a request or a response.

The Try an example button fills the input with a sample message so you can see the output without preparing your own text. Open a file loads a saved capture from disk. Clear empties both panes.

What the output shows

The right pane is labelled What it says. It breaks the message into named sections. The start line is identified as either a request line or a status line, and its pieces are labelled: the method, the path, and the protocol version for a request, or the protocol, the status code, and the reason phrase for a response.

Each header is listed with its name and value. Headers that appear more than once are flagged if the specification says they must not repeat. Two Content-Length headers, for instance, are a fault that a server is allowed to reject the entire message for.

The framing section is the most important part. It reports how the message says its body ends. There are three possibilities: a Content-Length header that states the byte count, a chunked Transfer-Encoding that breaks the body into labelled pieces, or no body at all. If both a length and a chunked encoding are present, the tool calls it out as a conflict.

The body section shows the raw body text and, if it was chunked, the reassembled version with the chunk markers removed. A byte count of the body is measured and compared against what Content-Length claims.

A worked example that explains a hanging request

Suppose you are writing a small HTTP client and your POST request never gets a response. You capture the raw text and it looks like this: POST /api/orders HTTP/1.1, then Host: shop.example.com, then Content-Type: application/json, then Content-Length: 27, then a blank line, then the body which is a JSON object with a name field containing cafe with an accent on the e.

You counted 27 characters in the JSON body and wrote that as the Content-Length. But the word cafe with an accent has a character that takes two bytes in UTF-8. The real byte count is 28, not 27. The server reads 27 bytes, sees an incomplete JSON object, and waits for the one remaining byte that never arrives. The request hangs until the server times out.

Paste this message into the inspector. The output measures the body at 28 bytes and compares it against the declared 27. The mismatch is reported clearly. Change the Content-Length to 28, send the request again, and the server answers immediately.

This is the single most common cause of a hand-written HTTP request that never gets a reply. Content-Length counts bytes, not characters, and any character outside the basic ASCII range takes more than one byte.

Chunked encoding and what it looks like raw

Some servers send the body in chunks instead of declaring its total length upfront. Each chunk starts with a line containing the chunk size in hexadecimal, followed by the chunk data, followed by a line break. The message ends with a chunk of size zero.

Reading this by hand is tedious and error-prone. The inspector decodes it for you. It reads each chunk size, joins the pieces together, and shows the reassembled body as a single block. If there is a trailer section after the final zero-length chunk, that is shown separately.

A message that carries both a Content-Length header and a chunked Transfer-Encoding is not just messy. It is a security risk. Two machines in a chain, such as a load balancer and an application server, can disagree about where the body ends. That disagreement is the foundation of request smuggling attacks. The inspector flags this conflict explicitly.

Line endings and the blank line rule

The HTTP specification requires lines to end with a carriage return followed by a line feed, written as CRLF. Many servers are forgiving and accept a bare line feed. But some are strict, and a request that works against one server can fail against another purely because of line endings.

The inspector reports what you actually pasted rather than silently fixing it. If your message uses bare line feeds, the output says so. That lets you know whether the line endings are a potential problem before you spend time looking elsewhere.

The blank line between the last header and the body is the most important single line in the whole message. Miss it and the server reads the first line of your body as a header. Add an extra blank line and the first line of your body becomes part of a larger gap that shifts everything by one line.

Mistakes that cost hours of debugging

  • Calculating Content-Length by counting characters instead of bytes. Any accented letter, emoji, or non-ASCII character takes more than one byte in UTF-8.
  • Sending both Content-Length and a chunked Transfer-Encoding. The specification says to ignore the length, but not all software follows the rule.
  • Omitting the blank line after the headers. The server has no way to know where headers end and the body begins without it.
  • Setting Content-Length to zero on a POST request that has a body. The server ignores the body and processes an empty request.
  • Assuming that a header can safely appear twice. Most headers must appear only once. A duplicate Host or Content-Length is a fault, not a convenience.
  • Pasting a message from a log that wrapped long lines. The line breaks that the log added are not in the original message and will break the parse.

When a different tool handles the job

  • To look up what a status code or MIME type means without inspecting a full message, the HTTP and File Type Lookup page is a faster reference.
  • To send a real HTTP request and see the response, you need a request client or the curl command. This tool reads messages but does not send them.
  • To test whether a URL responds and what headers it returns, a header checker or the browser's network panel gives you live data.
  • To decode a URL-encoded query string or form body, a URL decoder handles that step before you paste the decoded result here.

Your captured message stays on your own machine

The inspector reads the text you paste using your browser alone. It never makes a network request and never sends your message anywhere. That design is not just a feature. It is a necessity.

A captured HTTP request almost always contains an Authorization header, a session cookie, or an API key. Those credentials are as good as a password to anyone who intercepts them. Sending them to a third-party server to be parsed would defeat the purpose of examining them carefully. Here, the message stays in your browser's memory, and closing the tab is the only cleanup needed.

Help

The two mistakes that make a message hang

Paste either half of the conversation, a request or a response, and it is read the way a server reads it: start line first, then every header including the ones that turn up twice. The body is shown with any chunked encoding undone. Nothing is fetched and nothing is sent - it works only on the text sitting in the box.

Paste the whole message

Everything from the start line down to the end of the body, headers included. A copy out of a proxy, a curl trace or a log is exactly the right thing. Requests and responses are both understood, and which one you pasted is worked out for you.

Read the framing first

Before anything else, check how the message says its body ends. That one decision is what a server acts on, and it is where the faults that waste an afternoon live.

Compare the length with the bytes

The body is measured in UTF-8 bytes and set against what Content-Length claims. If they differ, that is your bug, and the number shown is the one to write.

Paste a real message and mind what is in it

A captured request usually carries an Authorization header, a session cookie or an API key, and those are as good as a password to anyone who gets them. That is the reason this tool works the way it does: the message is read by your own browser and never leaves the device, so pasting a live capture does not hand it to anybody. Do still think about where you paste it next — a bug report and a chat window are both public compared with this page.

Good to know

Content-Length is bytes, not characters

The word café is four characters and five bytes. A length worked out by counting characters leaves the server waiting for a byte that is never coming, and the request hangs until it times out. It is the commonest cause of a hand-written request that never answers.

Never send both length and chunked

A message carrying Content-Length and a chunked Transfer-Encoding is not merely untidy. Two machines in a chain can disagree about where it ends, and that disagreement is request smuggling. The specification says ignore the length; plenty of software does not.

Line endings have to be CRLF

HTTP separates lines with a carriage return and a line feed, not a line feed on its own. Plenty of servers forgive it and some do not, so what you actually pasted is reported either way rather than quietly cleaned up.

A blank line ends the headers

Exactly one empty line sits between the last header and the body. Miss it and the first line of your body is read as a header; add a second and it becomes part of the body.

Common questions

Does this send my request anywhere?
No, and it cannot. It never makes a request — it reads the text you paste. That is deliberate, because a captured message usually has credentials in it.
Why does my request hang with no answer?
Nine times out of ten the Content-Length is wrong. If it is larger than the body, the server waits for bytes that never arrive until it gives up. Paste the message here and the real byte count is measured for you.
Can it decode a chunked body?
Yes. Each chunk size is read, the pieces are joined back together, and any trailer after the final zero-length chunk is shown separately.
Will it read an HTTP/2 message?
Not in binary. HTTP/2 frames are not text and cannot be pasted. Most tools will show you an HTTP/2 exchange written out in the older text form, and that pastes in fine.
Why does it complain about a header appearing twice?
Some headers may repeat and some may not. Two Content-Length headers, or two Hosts, are a fault a server is entitled to reject the whole message for, so they are called out. Headers that are allowed to repeat are not.