HTTPCan

Send a request. See exactly what arrived.

HTTPCan is an HTTP test server for checking clients, proxies and AI agents. It covers every httpbin.org endpoint, fixes 18 of them, adds 33 more, and includes mock OpenAI, Anthropic and OAuth 2.0 servers.

Run your own copy

docker run -p 8080:8080 ghcr.io/seedvector/httpcan:latest
cargo install httpcan && httpcan
Request
GET
GET /get?hello=can HTTP/1.1
Host: httpcan.org
Response
Press Send to see what HTTPCan returns.

This page sent a real request to this server when it loaded. Change the path and press Send, or press Try next to any endpoint below. The same request from a terminal:

curl 'https://httpcan.org/get?hello=can'

Endpoints

Every example runs against this server (https://httpcan.org), so you can paste it straight into a terminal.

HTTP Methods

Testing different HTTP verbs.

  • /getGET

    Echoes the request's query parameters, headers, origin, and URL (GET and HEAD).

  • /postPOSTEnhanced

    Echoes the request's parsed body and uploaded files; same-named multipart fields collect into an array.

  • /putPUTEnhanced

    Same as /post, for PUT requests.

  • /patchPATCHEnhanced

    Same as /post, for PATCH requests.

  • /deleteDELETE

    Same as /post, for DELETE requests.

  • /headHEADNew

    HEAD-only: echoes the request headers back as X-Echo-* response headers.

  • /optionsOPTIONSNew

    OPTIONS-only: echoes the request and returns an Allow header (RFC 9110 §9.3.7).

  • /traceTRACENew

    TRACE-only: echoes the request like /anything (RFC 9110 §9.8).

  • /queryQUERYNew

    Echoes the request's URL args and parsed body, like /post (RFC 9430).

Anything

Returns anything that is passed to the request.

  • /anythingGET, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, QUERYEnhanced

    Accepts any method and echoes the full request; multipart handling matches /post.

  • /anything/{path}GET, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, QUERYEnhanced

    Same as /anything, with extra path segment(s) that are ignored.

Auth

Auth methods.

  • /basic-auth/{user}/{passwd}GET, POST

    Challenges HTTP Basic Auth with the given credentials.

  • /basic-auth/{user}GET, POSTNew

    Challenges HTTP Basic Auth with an empty password (username-only check).

  • /hidden-basic-auth/{user}/{passwd}GET, POST

    Like /basic-auth, but returns 404 instead of 401 on failure.

  • /hidden-basic-auth/{user}GET, POSTNew

    Like /basic-auth/{user}, but returns 404 instead of 401 on failure.

  • /bearerGET

    Checks for a Bearer token in the Authorization header.

  • /jwt-bearerGETNew

    Decodes and inspects a JWT Bearer token, without verifying its signature.

  • /digest-auth/{qop}/{user}/{passwd}[/{algorithm}[/{stale_after}]]GET, POSTEnhanced

    Challenges HTTP Digest Auth; adds SHA-512-256 and a qop=none legacy (RFC 2069) mode.

Status codes

Generates responses with a given status code.

  • /status/{codes}GET, POST, PUT, PATCH, DELETE, TRACE, OPTIONSEnhanced

    Returns the given status, or a random one from a comma-separated list; supports ?header= injection, a custom body, and trailing path segments.

Request inspection

Inspect the request data.

  • /headersGET

    Returns the request's HTTP headers.

  • /ipGET

    Returns the requester's IP address.

  • /user-agentGET

    Returns the request's User-Agent header.

  • /methodAny methodNew

    Returns the request's HTTP method name.

  • /bodyGET, POST, PUT, PATCH, DELETE, QUERYNew

    Returns the request's body verbatim with mirrored headers, for any method including QUERY (RFC 9430); /echo is a compatibility alias.

Response inspection

Inspect the response data, like caching and headers.

  • /cacheGET

    Returns 304 if If-Modified-Since or If-None-Match is present, 200 otherwise.

  • /cache/{value}GET

    Sets a Cache-Control header for the given number of seconds.

  • /etag/{etag}GETEnhanced

    Validates If-Match/If-None-Match against the given ETag; supports weak W/"..." validators.

  • /response-headersGET, POSTEnhanced

    Echoes query parameters as response headers; ?body= and ?status= override the response body and status code.

Response formats

Returns responses in different data formats.

  • /jsonGET

    Returns a sample JSON document.

  • /xmlGET

    Returns a sample XML document.

  • /htmlGET

    Returns a sample HTML document.

  • /denyGET

    Returns the page that robots.txt disallows.

  • /encoding/utf8GET

    Returns a UTF-8 encoded page.

  • /encoding/iso-8859-1GETNew

    Returns an ISO-8859-1 encoded page.

  • /gzipGET, POSTEnhanced

    GET returns gzip-encoded JSON; POST gzip-encodes the request body.

  • /deflateGET, POSTEnhanced

    GET returns deflate-encoded JSON; POST deflate-encodes the request body.

  • /brotliGET, POSTEnhanced

    GET returns brotli-encoded JSON; POST brotli-encodes the request body.

  • /zstdGET, POSTNew

    GET returns Zstandard-encoded JSON; POST zstd-encodes the request body.

Dynamic data

Generates random and dynamic data.

  • /uuidGET

    Returns a UUIDv4.

  • /base64/{value}GETEnhanced

    Decodes a standard base64 string; returns raw bytes for non-UTF-8 content instead of erroring.

  • /base64POSTNew

    Decodes the request body as base64.

  • /bytes/{n}GETEnhanced

    Returns n random bytes; over the configured --max-bytes limit returns 404 instead of silently truncating.

  • /stream-bytes/{n}GETEnhanced

    Streams n random bytes chunk by chunk; same limit behavior as /bytes.

  • /stream/{n}GET

    Streams n JSON lines describing the request.

  • /range/{numbytes}GET

    Streams numbytes bytes; supports Range requests.

  • /links/{n}/{offset}GET

    Returns a page of n links, starting at offset.

  • /links/{n}GETNew

    Same as /links/{n}/{offset}, with offset defaulted to 0.

  • /dripGETEnhanced

    Drips data over a duration; ?chunked=true streams with real chunked transfer-encoding.

  • /delay/{delay}GET, POST, PUT, PATCH, DELETE, TRACE

    Delays the response by up to 10 seconds.

Cookies

Creates, reads, and deletes cookies.

  • /cookiesGET

    Returns the request's cookies.

  • /cookies/setGETEnhanced

    Sets cookies from query parameters and redirects to /cookies; supports httponly/secure/samesite/domain/path/max_age attributes.

  • /cookies/set/{name}/{value}GET

    Sets a single cookie and redirects to /cookies.

  • /cookies/deleteGET

    Deletes the given cookies and redirects to /cookies.

Images

Returns different image formats.

  • /imageGET

    Returns a random image; format negotiated via the Accept header.

  • /image/pngGET

    Returns a PNG image.

  • /image/jpegGET

    Returns a JPEG image.

  • /image/webpGET

    Returns a WEBP image.

  • /image/svgGET

    Returns an SVG image.

Redirects

Returns different redirect responses.

  • /redirect/{n}GET

    Redirects n times before returning 200.

  • /relative-redirect/{n}GET

    Same as /redirect/{n}, using relative Location URLs.

  • /absolute-redirect/{n}GET

    Same as /redirect/{n}, using absolute Location URLs.

  • /redirect-toGET, POST, PUT, PATCH, DELETE, TRACEEnhanced

    Redirects to ?url=; POST/PUT/PATCH/DELETE also accept form/JSON bodies, and browser clients see an anti-phishing interstitial instead of a silent redirect.

Streaming

Server-Sent Events and NDJSON streaming endpoints.

  • /sseGETNew

    Streams server-sent events; supports OpenAI-compatible chunk formats.

  • /sse/{count}GETNew

    Same as /sse, with a fixed event count.

  • /sse/{count}/{delay}GETNew

    Same as /sse, with a fixed count and delay between events.

  • /ndjsonGETNew

    Streams newline-delimited JSON; supports OpenAI/Ollama-compatible chunk formats.

  • /ndjson/{count}GETNew

    Same as /ndjson, with a fixed line count.

  • /ndjson/{count}/{delay}GETNew

    Same as /ndjson, with a fixed count and delay between lines.

AI API Mock

Mock OpenAI- and Anthropic-compatible LLM APIs: point an SDK base_url at /llm and test without a paid provider.

  • /llmGETNew

    Self-describing index: endpoints, base_url guidance for both SDK families, and the httpcan response-override contract.

  • /llm/v1/chat/completionsPOSTNew

    Mock OpenAI Chat Completions API: canonical chat.completion shape, SSE streaming with [DONE], and an httpcan.content override. /llm/chat/completions works as a silent alias.

  • /llm/v1/messagesPOSTNew

    Mock Anthropic Messages API: content blocks, stop_reason, and the full streaming event protocol (message_start through message_stop).

  • /llm/v1/responsesPOSTNew

    Mock OpenAI Responses API: canonical Response object with output_text convenience field; streaming uses named SSE events (response.created through response.completed) with sequence numbers. /llm/responses works as a silent alias.

  • /llm/v1/completionsPOSTNew

    Mock OpenAI legacy Completions API (text-in/text-out): echo support, n choices, and SSE streaming with [DONE]. /llm/completions works as a silent alias.

  • /llm/v1/modelsGETNew

    Model list in the OpenAI shape, or the Anthropic shape when an anthropic-version header is present (both SDKs hit this same path).

  • /llm/v1/models/{model}GETNew

    Single-model lookup that always returns 200 and echoes the requested id — any model name is valid.

OAuth 2.0 Mock

Mock authorization server: RFC 6749 four grants with PKCE, one-time codes, rotating refresh tokens, and RFC 8414 discovery.

  • /oauth2GETNew

    Self-describing index: endpoints, supported grants, PKCE methods, and the mock's state semantics.

  • /oauth2/authorizeGET, POSTNew

    Authorization endpoint with a consent page. response_type=code issues a one-time authorization code (PKCE supported); response_type=token (implicit, legacy) returns the access token in the redirect fragment.

  • /oauth2/tokenPOSTNew

    Token endpoint: authorization_code (+PKCE), password, refresh_token (rotating), and client_credentials grants; Basic and form-body client authentication.

  • /oauth2/userinfoGET, POSTNew

    Bearer-protected resource: verifies the access token and returns the mock identity (sub/email/client_id/scope).

Observability

Health checks and instance identification.

  • /healthzGETNew

    Liveness probe: returns 200 whenever the server is up.

  • /tagsGETNew

    Returns all HTTPCAN_* environment variables, for instance identification.

  • /tags/{name}GETNew

    Returns a single HTTPCAN_* environment variable by name.

What HTTPCan adds to httpbin.org

Mock AI APIs
OpenAI- and Anthropic-compatible endpoints under /llm. Point an SDK’s base_url at them to test your client, streaming included, without a paid key.
Mock OAuth 2.0 server
All four RFC 6749 grants with PKCE, one-time codes, rotating refresh tokens, a Bearer-protected userinfo endpoint and RFC 8414 discovery, under /oauth2.
Streaming endpoints
/sse and /ndjson send OpenAI- and Ollama-shaped chunks, so you can test streaming parsers.
Safer redirects
Browsers that open /redirect-to see a confirmation page instead of a silent 302, so the endpoint can’t be abused as an open redirect.
Headers kept intact
Duplicate and non-ASCII request headers are echoed back as sent instead of being dropped.
Proxy headers filtered
About 100 reverse-proxy and CDN headers are removed from echoed responses. Add your own with --exclude-headers.
Health checks
/healthz for liveness probes, /tags for instance identification, and Server-Timing and X-Httpcan-Version headers on every response.
Fast
Built with Rust and Actix Web. In our benchmarks it led comparable test servers on throughput and tail latency.