HTTP Headers Parser

Paste headers copied from curl -i, browser dev tools or a proxy log. You get a tidy message with canonical header names, a plain-English summary and a formatted body.

Input

Settings

History

Load from URL

What counts as an HTTP message here

An HTTP/1.x message is a start line, a block of Name: value header fields, an empty line and an optional body. The start line is either a request line (GET /api/orders?page=2 HTTP/1.1) or a status line (HTTP/1.1 404 Not Found). The parser accepts all three shapes people actually paste: a full request or response, a response with its body, or just the header lines without any start line, which is what most dev tools copy.

HTTP/2 and HTTP/3 send the same headers in binary frames, but tools such as curl -i print them in this text form with a HTTP/2 200 status line, so those pastes work too.

Using the parser

Paste into the input pane; formatting runs as you type, and Ctrl/Cmd+Enter re-runs it on demand. The built-in HTTP message parser rewrites the message in a consistent shape:

  • Header names get their canonical casing: content-type becomes Content-Type and x-request-id becomes X-Request-ID. Unknown custom headers are left as written. When the status line says HTTP/2 or later, names are lower-cased instead, because that is how they travel on the wire.
  • Obsolete folded header values (continuation lines starting with a space) are joined into one line, with a warning.
  • A body after the blank line is pretty-printed when its Content-Type or content is JSON, XML or HTML, and application/x-www-form-urlencoded bodies are listed field by field. Compressed bodies (a Content-Encoding such as gzip) are left untouched.

The info panel explains what the headers mean together. The Status row gives the reason phrase and what the code means, for example that a 301 means links should be updated to the Location. Caching turns Cache-Control into a sentence such as “Fresh for 1 year; never changes while fresh”. Every Set-Cookie gets a row listing its flags: HttpOnly, Secure, SameSite, Path, and whether it is a session cookie, expires later or deletes the cookie. The Table view lists each header with its value and a one-line meaning. There are no format-specific options.

Problems it catches

Several mistakes in raw messages cause real outages, and the parser reports them as warnings with the line number:

  • A Content-Length that does not match the body. The check allows for CRLF line endings and a trailing newline, so it only fires on a genuine mismatch.
  • Both Content-Length and Transfer-Encoding present, a classic request-smuggling ingredient.
  • Repeated headers that must appear once, such as Content-Type or Host, especially with conflicting values.
  • An HTTP/1.1 request without a Host header.
  • Lower-case methods (get is not GET; methods are case-sensitive), a missing HTTP version on the request line, malformed status codes and header names containing spaces.

A body declared as JSON that does not parse is shown as written, with a warning instead of an error, so you can still read it.

A note on what you paste

Raw headers routinely contain Authorization bearer tokens, session cookies and API keys. Parsing happens in your browser and the message is not uploaded, but redact credentials before pasting the formatted result into a ticket or chat. If a header carries a JWT, the JWT decoder will show its claims and expiry.

Examples

Redirect response with long-lived caching

Names are re-cased, the cache rule is summarised as one year and immutable, and the cookie is recognised as a deletion.

Input
HTTP/1.1 301 Moved Permanently
location: https://www.example.com/new-path
cache-control: max-age=31536000, immutable
set-cookie: tracking=off; Max-Age=0; Path=/
vary: accept-encoding
Output
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/new-path
Cache-Control: max-age=31536000, immutable
Set-Cookie: tracking=off; Max-Age=0; Path=/
Vary: accept-encoding
Open this example in the tool

JSON POST request with its body

The body after the empty line is pretty-printed as JSON, and its 57 bytes match the declared Content-Length.

Input
POST /api/orders HTTP/1.1
host: api.example.com
content-type: application/json
accept: application/json
content-length: 57

{"sku":"KB-104","qty":1,"shipping":"express","gift":true}
Output
POST /api/orders HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
Content-Length: 57

{
  "sku": "KB-104",
  "qty": 1,
  "shipping": "express",
  "gift": true
}
Open this example in the tool

HTTP/2 response copied from curl -i

Because the status line says HTTP/2, header names are written in lower case as HTTP/2 requires.

Input
HTTP/2 200
Content-Type: text/html; charset=utf-8
Cache-Control: private, no-cache
Strict-Transport-Security: max-age=63072000
Output
HTTP/2 200
content-type: text/html; charset=utf-8
cache-control: private, no-cache
strict-transport-security: max-age=63072000
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
This does not look like a request line ("METHOD /path HTTP/1.1") or a header ("Name: value")The first line is neither a start line nor a header, often a log prefix or a timestamp copied along with the message.Delete everything before the request line or the first header.
Expected a header line "Name: value"A line without a colon appears among the headers, usually because the empty line before the body is missing.Insert a blank line between the last header and the body.
The request line is missing the HTTP versionThe request line has a method and path but no protocol, as in GET /api/orders.Add the version at the end, for example GET /api/orders HTTP/1.1.
Content-Length says 52 bytes but the body is 57 bytesThe declared length was not updated after the body was edited. A server would cut the body short or wait for missing bytes.Let your HTTP client compute Content-Length, or set it to the UTF-8 byte length of the body, not the character count.
Methods are case-sensitive: "get" should be "GET"HTTP methods are case-sensitive tokens, and most servers reject lower-case ones with 400 or 405.Write the method in upper case.

Frequently asked questions

How do I copy raw HTTP headers from Chrome or Firefox?

In the Network panel, select the request and use the Raw toggle in the Headers tab, or right-click the request and choose Copy as cURL. Running that command with curl -i prints a response this parser reads directly.

Are HTTP header names case-sensitive?

No, servers must treat them case-insensitively. The parser still normalises them to the usual capitalisation for HTTP/1.x so messages are easier to compare.

What does Cache-Control: no-cache actually mean?

The response may be stored, but it must be revalidated with the server before every use. To forbid storing it at all, use no-store; the Caching row spells out the difference for each directive.

Can it read an HTTP/2 response?

Yes, in the text form tools like curl print. The status line HTTP/2 200 is accepted and header names are kept in lower case.

Related tools