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:latestcargo install httpcan && httpcanPress 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.
/getGETEchoes the request's query parameters, headers, origin, and URL (GET and HEAD).
/postPOSTEnhancedEchoes the request's parsed body and uploaded files; same-named multipart fields collect into an array.
/putPUTEnhancedSame as /post, for PUT requests.
/patchPATCHEnhancedSame as /post, for PATCH requests.
/deleteDELETESame as /post, for DELETE requests.
/headHEADNewHEAD-only: echoes the request headers back as X-Echo-* response headers.
/optionsOPTIONSNewOPTIONS-only: echoes the request and returns an Allow header (RFC 9110 §9.3.7).
/traceTRACENewTRACE-only: echoes the request like /anything (RFC 9110 §9.8).
/queryQUERYNewEchoes 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, QUERYEnhancedAccepts any method and echoes the full request; multipart handling matches /post.
/anything/{path}GET, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, QUERYEnhancedSame as /anything, with extra path segment(s) that are ignored.
Auth
Auth methods.
/basic-auth/{user}/{passwd}GET, POSTChallenges HTTP Basic Auth with the given credentials.
/basic-auth/{user}GET, POSTNewChallenges HTTP Basic Auth with an empty password (username-only check).
/hidden-basic-auth/{user}/{passwd}GET, POSTLike /basic-auth, but returns 404 instead of 401 on failure.
/hidden-basic-auth/{user}GET, POSTNewLike /basic-auth/{user}, but returns 404 instead of 401 on failure.
/bearerGETChecks for a Bearer token in the Authorization header.
/jwt-bearerGETNewDecodes and inspects a JWT Bearer token, without verifying its signature.
/digest-auth/{qop}/{user}/{passwd}[/{algorithm}[/{stale_after}]]GET, POSTEnhancedChallenges 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, OPTIONSEnhancedReturns 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.
/headersGETReturns the request's HTTP headers.
/ipGETReturns the requester's IP address.
/user-agentGETReturns the request's User-Agent header.
/methodAny methodNewReturns the request's HTTP method name.
/bodyGET, POST, PUT, PATCH, DELETE, QUERYNewReturns 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.
/cacheGETReturns 304 if If-Modified-Since or If-None-Match is present, 200 otherwise.
/cache/{value}GETSets a Cache-Control header for the given number of seconds.
/etag/{etag}GETEnhancedValidates If-Match/If-None-Match against the given ETag; supports weak W/"..." validators.
/response-headersGET, POSTEnhancedEchoes query parameters as response headers; ?body= and ?status= override the response body and status code.
Response formats
Returns responses in different data formats.
/jsonGETReturns a sample JSON document.
/xmlGETReturns a sample XML document.
/htmlGETReturns a sample HTML document.
/denyGETReturns the page that robots.txt disallows.
/encoding/utf8GETReturns a UTF-8 encoded page.
/encoding/iso-8859-1GETNewReturns an ISO-8859-1 encoded page.
/gzipGET, POSTEnhancedGET returns gzip-encoded JSON; POST gzip-encodes the request body.
/deflateGET, POSTEnhancedGET returns deflate-encoded JSON; POST deflate-encodes the request body.
/brotliGET, POSTEnhancedGET returns brotli-encoded JSON; POST brotli-encodes the request body.
/zstdGET, POSTNewGET returns Zstandard-encoded JSON; POST zstd-encodes the request body.
Dynamic data
Generates random and dynamic data.
/uuidGETReturns a UUIDv4.
/base64/{value}GETEnhancedDecodes a standard base64 string; returns raw bytes for non-UTF-8 content instead of erroring.
/base64POSTNewDecodes the request body as base64.
/bytes/{n}GETEnhancedReturns n random bytes; over the configured --max-bytes limit returns 404 instead of silently truncating.
/stream-bytes/{n}GETEnhancedStreams n random bytes chunk by chunk; same limit behavior as /bytes.
/stream/{n}GETStreams n JSON lines describing the request.
/range/{numbytes}GETStreams numbytes bytes; supports Range requests.
/links/{n}/{offset}GETReturns a page of n links, starting at offset.
/links/{n}GETNewSame as /links/{n}/{offset}, with offset defaulted to 0.
/dripGETEnhancedDrips data over a duration; ?chunked=true streams with real chunked transfer-encoding.
/delay/{delay}GET, POST, PUT, PATCH, DELETE, TRACEDelays the response by up to 10 seconds.
Cookies
Creates, reads, and deletes cookies.
/cookiesGETReturns the request's cookies.
/cookies/setGETEnhancedSets cookies from query parameters and redirects to /cookies; supports httponly/secure/samesite/domain/path/max_age attributes.
/cookies/set/{name}/{value}GETSets a single cookie and redirects to /cookies.
/cookies/deleteGETDeletes the given cookies and redirects to /cookies.
Images
Returns different image formats.
/imageGETReturns a random image; format negotiated via the Accept header.
/image/pngGETReturns a PNG image.
/image/jpegGETReturns a JPEG image.
/image/webpGETReturns a WEBP image.
/image/svgGETReturns an SVG image.
Redirects
Returns different redirect responses.
/redirect/{n}GETRedirects n times before returning 200.
/relative-redirect/{n}GETSame as /redirect/{n}, using relative Location URLs.
/absolute-redirect/{n}GETSame as /redirect/{n}, using absolute Location URLs.
/redirect-toGET, POST, PUT, PATCH, DELETE, TRACEEnhancedRedirects 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.
/sseGETNewStreams server-sent events; supports OpenAI-compatible chunk formats.
/sse/{count}GETNewSame as /sse, with a fixed event count.
/sse/{count}/{delay}GETNewSame as /sse, with a fixed count and delay between events.
/ndjsonGETNewStreams newline-delimited JSON; supports OpenAI/Ollama-compatible chunk formats.
/ndjson/{count}GETNewSame as /ndjson, with a fixed line count.
/ndjson/{count}/{delay}GETNewSame 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.
/llmGETNewSelf-describing index: endpoints, base_url guidance for both SDK families, and the httpcan response-override contract.
/llm/v1/chat/completionsPOSTNewMock 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/messagesPOSTNewMock Anthropic Messages API: content blocks, stop_reason, and the full streaming event protocol (message_start through message_stop).
/llm/v1/responsesPOSTNewMock 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/completionsPOSTNewMock 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/modelsGETNewModel 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}GETNewSingle-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.
/oauth2GETNewSelf-describing index: endpoints, supported grants, PKCE methods, and the mock's state semantics.
/oauth2/authorizeGET, POSTNewAuthorization 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/tokenPOSTNewToken endpoint: authorization_code (+PKCE), password, refresh_token (rotating), and client_credentials grants; Basic and form-body client authentication.
/oauth2/userinfoGET, POSTNewBearer-protected resource: verifies the access token and returns the mock identity (sub/email/client_id/scope).
Observability
Health checks and instance identification.
/healthzGETNewLiveness probe: returns 200 whenever the server is up.
/tagsGETNewReturns all HTTPCAN_* environment variables, for instance identification.
/tags/{name}GETNewReturns 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’sbase_urlat 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
/sseand/ndjsonsend OpenAI- and Ollama-shaped chunks, so you can test streaming parsers.- Safer redirects
- Browsers that open
/redirect-tosee 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
/healthzfor liveness probes,/tagsfor instance identification, andServer-TimingandX-Httpcan-Versionheaders on every response.- Fast
- Built with Rust and Actix Web. In our benchmarks it led comparable test servers on throughput and tail latency.