Testserver

A public test server for HTTP & friends, built as part of HTTP Toolkit.

Source code available at github.com/httptoolkit/testserver.

HTTP Endpoints

Request Inspection (7)
/{method} Returns request info for the specified HTTP method. Returns 405 if the request method does not match the path./get /post /put /patch /delete
/anything Returns JSON containing the parsed details of the request, including method, url, headers, args, data, files, form, and origin./anything/subpath
/echo Echoes back the raw HTTP request data. For HTTP/2, returns parsed frame data as JSON lines.
/headers Returns the request headers as JSON.
/ip Returns the client's IP address.
/trailers Tests HTTP trailers. Returns any received trailers and sends trailers back if the client indicated support via the TE header.
/user-agent Returns the User-Agent header from the request.
Custom Responses (2)
/response-headers Returns a response with headers set from the query parameters./response-headers?X-Custom=value /response-headers?freeform=hello&freeform=world
/status/{code} Returns a response with the specified HTTP status code./status/200 /status/404 /status/500
Redirects (4)
/absolute-redirect/{n} Redirects n times using absolute URLs, then returns /get./absolute-redirect/3
/redirect-to Redirects to the URL specified in the "url" query parameter, with an optional "status_code" (default 302)./redirect-to?url=/get /redirect-to?url=/get&status_code=301
/redirect/{n} Redirects n times using relative URLs (via /relative-redirect), then returns /get./redirect/3
/relative-redirect/{n} Redirects n times using relative URLs, then returns /get./relative-redirect/3
Caching (3)
/cache Returns 304 Not Modified if an If-Modified-Since or If-None-Match header is present, otherwise returns the same response as /get.
/cache/{n} Sets a Cache-Control header for n seconds, then returns the same response as /get./cache/60
/etag/{etag} Assumes the given etag for the resource and responds according to If-None-Match and If-Match request headers./etag/my-etag
Authentication (3)
/basic-auth/{username}/{password} Challenges with HTTP Basic Auth, expecting the username & password from the URL. Returns 200 with user info on success, 401 if unauthenticated, 403 if wrong credentials./basic-auth/admin/secret
/bearer Checks for a Bearer token in the Authorization header. Returns 200 with token info on success, 401 if missing.
/hidden-basic-auth/{username}/{password} Like /basic-auth but returns 404 instead of 401 on authentication failure./hidden-basic-auth/admin/secret
Cookies (3)
/cookies Returns the cookies sent with the request.
/cookies/delete Deletes cookies specified in query parameters, then redirects to /cookies./cookies/delete?name
/cookies/set Sets cookies via query parameters or path segments, then redirects to /cookies./cookies/set?name=value /cookies/set/name/value
Response Formats (7)
/deny Returns a page denied by robots.txt.
/encoding/utf8 Returns a UTF-8 encoded HTML page with various Unicode characters.
/html Returns an HTML page.
/json Returns a sample JSON document.
/robots.txt Returns a robots.txt file that disallows crawling of all paths except the root.
/xml Returns a sample XML document.
example Returns a copy of the example.com HTML page. Access via the example subdomain prefix.https://example.testserver.host/
Response Encoding (5)
/encoding/brotli Returns brotli-encoded JSON data.
/encoding/deflate Returns deflate-encoded JSON data.
/encoding/gzip Returns gzip-encoded JSON data.
/encoding/identity Returns uncompressed JSON data with content-encoding: identity.
/encoding/zstd Returns zstd-encoded JSON data.
Dynamic Data (7)
/base64/{value} Decodes a base64url-encoded string and returns the decoded value./base64/SGVsbG8gd29ybGQ=
/bytes/{n} Returns n random bytes. Supports an optional "seed" query parameter for deterministic output./bytes/1024
/delay/{seconds} Delays the response by the specified number of seconds (max 10). Can be chained with other endpoints./delay/1 /delay/5 /delay/2/status/200
/stream-bytes/{n} Streams n random bytes in chunks. Supports optional "chunk_size" (default 10240) and "seed" query parameters./stream-bytes/1024
/stream/{n} Streams n newline-delimited JSON objects, each containing request data with an incrementing id./stream/5
/uuid Returns a randomly generated UUID v4.
/version Returns the testserver.host server version hash as JSON.
TLS Inspection (2)
/tls/client-hello Returns the fully parsed TLS ClientHello. Requires HTTPS.
/tls/fingerprint Returns the TLS fingerprint (JA3 and JA4) of the client connection. Requires HTTPS.
Errors (2)
/error/close Immediately closes the connection without sending a response.
/error/reset Resets the connection (sends a TCP RST) without sending a response.

WebSocket Endpoints

Connect via wss://{hostname}/ws/...

Messaging (3)
/ws/echo Echoes back any messages received.
/ws/message/{text} Sends the specified message to the client upon connection. Can be chained with other WS endpoints./ws/message/hello /ws/message/hello/echo
/ws/repeat/{message}/{intervalMs} Repeatedly sends the specified message at the given interval (in milliseconds). Can be chained with other WS endpoints./ws/repeat/ping/1000 /ws/repeat/heartbeat/5000/echo
Connection (3)
/ws/close/{code} Closes the WebSocket connection with the specified close code (1000-4999). Optional reason via query parameter./ws/close /ws/close/1001 /ws/close/4000?reason=custom
/ws/no-subprotocol Explicitly omits the Sec-WebSocket-Protocol header from the upgrade response, overriding the default behavior where the server auto-selects the first client-offered protocol./ws/no-subprotocol/echo
/ws/subprotocol/{name} Forces the specified subprotocol in the upgrade response Sec-WebSocket-Protocol header, regardless of what the client requested./ws/subprotocol/graphql-ws/echo /ws/subprotocol/mqtt/message/hello/close/1000
Timing (1)
/ws/delay/{seconds} Delays WebSocket connection handling by the specified seconds (max 10). Can be chained with other WS endpoints./ws/delay/1/echo /ws/delay/5/close
Errors (1)
/ws/error/reset Destroys the WebSocket connection abruptly without a proper close handshake.

TLS Endpoints

The TLS endpoint(s) to use are specified by subdomain, e.g. expired.{domain}.

Endpoints can be combined using double-dashes, e.g. expired--revoked--http2--tls-v1-2.{domain} will return an expired and revoked certificate, use TLSv1.2, and then negotiate HTTP/2 on the connection.

These can also be combined with the HTTP or WebSocket handlers above, which can be independently specified in the request path.

example An example subdomain that serves an exact copy of the classic example.com page as the root page (instead of these docs).https://example.testserver.host/
no-tls Rejects the TLS handshake with a connection reset, simulating a server that does not support TLS.https://no-tls.testserver.host/
Certificate Modes (5)
Protocol Negotiation (2)

Endpoints that negotiate specific protocols via ALPN. These can be used together, to simulate a server supporting specific combinations of protocols, in the preference order specified.

TLS Versions (4)

Endpoints that only accept specific TLS versions. These can be used together, to simulate a server supporting any specific combination of versions.