HTTP Response Builder
Build a raw HTTP response from a status code, headers and a body, with the registered reason phrase, CRLF line endings and a Content-Length, and warnings for mistakes such as a Content-Length that is not the body's length.
Leave it empty for the code's registered name.
About HTTP Response Builder
The response is written as a server sends it over HTTP/1.1: the status line and each field on a line that ends in CRLF, then an empty line, then the body (RFC 9112 §2.1). The status line has the code's name in IANA's registry as its reason phrase, as in HTTP/1.1 404 Not Found, unless you type another. A code with no name there, such as 299, gets a note that a client treats a code it does not know as the x00 of its class (RFC 9110 §15), and 306 and 418, which RFC 9110 reserves, get a note saying so instead.
When the response has neither Content-Length nor Transfer-Encoding, Content-Length is added, as the body's length in bytes in UTF-8, unless you choose Leave out: without either, an HTTP/1.1 body ends only where the server closes the connection (RFC 9112 §6.3). No Content-Length is added to a 1xx, 204 or 304 response, which ends with its fields. With Transfer-Encoding: chunked, a body is written as one chunk, its length in hexadecimal before it, then the chunk of length 0 that ends it. A body typed for a 1xx, 204, 205 or 304 response is left out, with a warning, as RFC 9110 allows such a response no content.
A warning says when the response breaks a rule of HTTP, or when Node's http client or its fetch, measured on Node v24.15.0, would refuse it or read it otherwise than meant. LF alone at the end of a line, a field name with a space, a Content-Length that is not the body's length, and Content-Length sent with Transfer-Encoding each get one. Seven presets start from a common response, such as a 401 with the WWW-Authenticate challenge RFC 9110 requires of it, and each builds with no warning on HTTP/1.1.
HTTP/2 and HTTP/3 send a response as frames, so for them it is shown as text to read: the status code alone, the field names in lowercase, and no Connection, Keep-Alive, Proxy-Connection, TE, Transfer-Encoding or Upgrade field, as those versions do not allow them (RFC 9113 §8.2.2, RFC 9114 §4.2).
Copy and Download give the response with its CRLF line endings, but the box shows every line break alike, so tick Show line endings to see how each line ends. Everything runs in your browser. The link keeps the version, the status code, the line endings and the Content-Length option, but not the reason phrase, the fields or the body, as a field can hold a token.
To build the request, see HTTP Request Builder. For what each code means, see HTTP Status Code Reference, and for caching fields, Cache-Control Builder.
Built and maintained by Meet Shah · Last updated
What this tool is used for
- Writing the exact bytes a mock server or a test stub sends back, with CRLF line endings and a Content-Length that matches the body in bytes.
- Checking a hand-written response before a test relies on it: a warning names a Content-Length that is not the body's length, a 401 without
WWW-Authenticate, or a redirect withoutLocation. - Showing a raw HTTP/1.1 response in API documentation, with the registered reason phrase in its status line.
- Seeing what Node's http client and fetch make of a response that breaks a rule, such as Content-Length given twice, which both refuse, or a reason phrase beyond ASCII, which they read differently.
- Writing a chunked response by hand: the body's length in hexadecimal before it, then the chunk of length 0 and the empty line that end the body.
Frequently Asked Questions
- Why does each line end in CRLF?
- HTTP/1.1 ends the status line and each field line with CRLF, and an empty line ends the fields (RFC 9112 §2.1). RFC 9112 §2.2 lets a client accept LF alone but does not require it, and Node's http client and fetch refuse a response whose lines end in LF alone. Choose LF alone only to see what a client makes of it.
- Does the reason phrase matter?
- A client SHOULD ignore it (RFC 9112 §4), but Node's http client shows it as
statusMessageand its fetch asstatusText, so code can still read it. HTTP/2 sends the code alone, in:status(RFC 9113 §8.3.2), and HTTP/3 has no way to carry a reason phrase (RFC 9114 §4.3.2). - What is the difference between 401 and 403?
- A 401 says the request lacks valid credentials for the resource, and it MUST have a
WWW-Authenticatefield with a challenge (RFC 9110 §15.5.2). A 403 says the server understood the request but refuses it; credentials, if any were sent, are not enough (§15.5.4). The builder warns of a 401 withoutWWW-Authenticate. - When is a 422 right rather than a 400?
- A 400 says the server cannot or will not process the request for what it sees as a client error, such as malformed syntax (RFC 9110 §15.5.1). A 422, named Unprocessable Content, says the syntax is correct but the instructions could not be processed, as in well-formed but semantically erroneous XML (§15.5.21).
- 301, 302, 307 or 308?
- 301 and 308 are permanent, 302 and 307 temporary. 307 and 308 were added to keep the method, and 301 and 302 allow a POST to be redirected as GET (RFC 9110 §15.4). A cache may reuse a 301 or 308 for a time it estimates unless a field such as Cache-Control says otherwise (§15.1). Each SHOULD have a
Locationfield. - Why is Content-Length added?
- Without Content-Length or Transfer-Encoding, an HTTP/1.1 body ends only when the server closes the connection (RFC 9112 §6.3), so on a connection kept open, Node's http client and fetch wait. Choose Leave out to end the body with the close. A typed Content-Length is kept and checked against the body's length in bytes.
- Can a 204 or 304 response have a body?
- No: a 1xx, 204 or 304 response ends with its fields and cannot have content (RFC 9110 §15.2, §15.3.5, §15.4.5), and a server MUST NOT generate content in a 205 (§15.3.6). A body typed for one is left out with a warning: Node's http client reads bytes after a 204 or 304 as the start of the next response, and fails.
Common errors and gotchas
- Joining the lines with a newline alone, as a multi-line string in code usually does, so each ends in LF rather than CRLF: Node's http client and fetch refuse such a response.
- Counting characters rather than bytes for Content-Length: a character beyond ASCII takes 2 to 4 bytes in UTF-8, so Node's fetch drops the end of the body and its http client fails on it.
- Sending Content-Length with
Transfer-Encoding: chunked, which a sender MUST NOT do (RFC 9112 §6.2), and which Node's http client and fetch refuse. - Writing
Transfer-Encoding: chunkedover a body that is not in chunks: a client reads the start of the body as a chunk size, and on a JSON body Node's http client and fetch fail with Invalid character in chunk size. - Writing a field name with a space, such as Content Type: a name is a token (RFC 9110 §5.1), and Node's http client and fetch refuse the response.
- Sending Access-Control-Allow-Origin twice, as when both an app and its proxy add it: a browser reads the two as one value, *, *, which is neither * nor an origin, so its CORS check fails and the page cannot read the response.