HTTP Client
Send REST requests from your browser — import & export curl.
Runs online in your browserNo installNo accountFree
How to use HTTP Client
- Pick a method and paste the URL, or click a preset like GitHub API, JSONPlaceholder, or httpbin echo to prefill a working request you can edit.
- Add headers with the "+ Add header" button. Auth-style keys (`Authorization`, `X-API-Key`, `Api-Key`, `Anthropic-Api-Key`, `Openai-Api-Key`) are automatically masked so tokens don't leak on screen-share.
- Pick an HTTP version if the target server's protocol matters — this changes the emitted curl only, not the in-browser Send.
- For POST/PUT/PATCH/DELETE, fill in the body — JSON, form-urlencoded, XML, or raw bytes. The editor places a JSON stub when your Content-Type header names JSON.
- Scan the live curl preview to confirm your request looks right, or paste a curl command from browser devtools and click "Import curl → request" to hydrate the editor from it.
- Hit Send (or press Enter inside the URL field). The request goes directly to the target server; the response panel shows status, elapsed ms, content type, and the rendered body.
- Browse the response — body with auto-JSON-pretty-printing, headers as a searchable table, or the raw HTTP response text with status line plus headers plus body.
- Click "Copy as curl" or "Copy as fetch" to export the current request for your terminal, a CI job, or a code snippet pasted straight into your app.
HTTP Client
A browser-native REST client for quickly testing API endpoints — GitHub, Stripe, Anthropic, OpenAI, an internal staging service, whatever is in front of you. The request is sent directly from your browser to the target server using the same fetch() API your app uses in production. No proxy, no relay, no logging. If it fails with CORS, Copy as curl gives you a terminal-equivalent in one click.
Why a browser-based HTTP client
The existing options are heavier than they need to be. Postman ships a desktop app, requires sign-in, and syncs history to their servers. Insomnia is similar. Bruno is lighter but still an install. Hoppscotch is browser-based but cloud-sync by default. For the 90% case of "let me poke this one endpoint for a minute" you want a fetch wrapper with a nice form on top, a real curl generator that round-trips, and zero onboarding. That is this tool.
Scoped small:
- One request at a time — no collections, environments, or variable substitution.
- One-click curl import/export — Chrome, Firefox, and Safari devtools pastes work unchanged, including multi-line
\-continued commands. - Live curl preview — updates every keystroke, so you copy without second-guessing serialization.
- HTTP version selector that round-trips through the parser —
--http2and--http3flags survive paste → edit → export. - Response rendered three ways — pretty body, header table, raw HTTP text.
- API keys never written to storage.
If you need saved environments and history, Postman is a better fit. For the quick poke, an on-call curl generator, or a shareable fetch() snippet for a PR, this is faster and leaves no trail.
What it does
- Method + URL + Send — all seven standard methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS) plus Enter-to-send from the URL field. Invalid URLs block Send with a validation banner.
- Header editor with sensitive-value masking — names matching
Authorization,X-API-Key,Api-Key,Anthropic-Api-Key, orOpenai-Api-Keyrender astype="password", so screen-shares do not broadcast tokens. - HTTP version selector —
auto,HTTP/1.0,HTTP/1.1,HTTP/2, orHTTP/3. Applies to the copied curl only — browsers negotiate the wire version via ALPN and do not expose the choice to JavaScript. Useful for reproducing protocol-specific server bugs. - Live curl preview — pretty multi-line curl above the import panel, updating every keystroke. Same serializer as Copy as curl, so the clipboard matches what you see.
- Curl import — paste a curl and hydrate method, URL, headers, body, and HTTP version. The parser handles
-X,-H,-d,--data-raw,--data-binary,--data-urlencode,-u(→Authorization: Basic …),-A(→User-Agent),-e(→Referer),--http1.0,--http1.1,--http2,--http2-prior-knowledge,--http3,--http3-only. Browser-irrelevant flags (--compressed,-k,-s,-L,-v,-i,-4,-6) are silently ignored. - Curl and fetch export — Copy as curl emits the preview command; Copy as fetch emits an
await fetch(url, { method, headers, body })line. - Presets — GitHub API (with
AcceptandX-GitHub-Api-Version), JSONPlaceholder, and httpbin echo. - Response panel with three tabs — Body auto-JSON-pretty-prints, Headers as a table, Raw as the full status + headers + body block. Badges colour-code status (2xx/3xx/4xx/5xx), report elapsed ms from
performance.now(), and pin content type. - One-click clear — wipes URL, headers, body, paste buffer, and response, then refocuses the URL field.
Under the hood
The tool splits into a pure transform layer and a thin React shell. transform.ts contains the curl parser, curl serializer, fetch-snippet serializer, URL validator, and JSON body formatter — all Result<T, E>-returning functions with zero DOM or network dependencies. Quoted tokens, \-line continuations, header smuggling detection, and body reassembly from repeated -d flags are all pure functions with real unit tests.
The shell owns two pieces of state: the current HttpRequest and the last ResponseSnapshot. On Send it validates the URL (must parse with new URL(...), must be http: or https:), builds a RequestInit, calls fetch(url, init) exactly once timed with performance.now(), reads the body as text, and opportunistically JSON.parses bodies starting with { or [.
CORS is a browser rule, not a tool limitation
Browsers restrict cross-origin requests unless the target returns Access-Control-Allow-Origin. Most modern APIs do; many legacy APIs and most internal services do not. When you hit a CORS wall, fetch throws TypeError: Failed to fetch — we surface that verbatim and point you at Copy as curl. Your terminal does not enforce CORS. The only workaround would be a server-side proxy, which would route your tokens through our server and defeat the privacy story.
Why the HTTP version selector only affects the curl output
The browser fetch() API cannot pin a wire-protocol version. ALPN in the TLS handshake picks it — HTTP/3 over QUIC when the server publishes Alt-Svc: h3=":443", HTTP/2 otherwise, HTTP/1.1 as a last resort. JavaScript cannot override it or learn what it was. The selector exists because the copied curl is frequently the thing you actually run in anger, and --http2 versus --http3-only is load-bearing for reproducing protocol-specific server bugs. The parser round-trips those flags, so pasting a curl with --http2-prior-knowledge restores the selector to HTTP/2 and re-exports cleanly.
The pure transform layer
Curl preview, Copy as curl, Copy as fetch, and the round-trip path all call the same pure functions — "what you see is what lands in your clipboard" is a structural guarantee.
Privacy — runs entirely in the browser
Every byte stays in the page. The request goes from your tab to the target server with zero intermediate hops beyond the DNS/TCP/QUIC/TLS your browser does for any outbound call. No backend — the HTTP Client is a React component, the transform layer plain TypeScript, and Send triggers exactly one network call. Verify in devtools' Network tab.
API keys pasted into header rows live in React state only — not localStorage, sessionStorage, IndexedDB, or cookies. Reload and they are gone. Deliberate trade-off: no session persistence, nothing survives a refresh. To keep the request, copy the curl preview into a private notebook or ticket.
Masking on sensitive header values is defence in depth — screen-shares and pair-programming do not broadcast the token as plain text. The value is still sent literally on the wire; the masking is about pixels, not bytes.
What's not supported (yet)
- Persistent collections and request history — one request at a time, no saved list. Copy the curl into your notes; pasting it back fully reconstructs method, headers, body, and HTTP version.
- Cookie jar — browsers own the cookie jar and block JavaScript from setting
Cookiefor cross-origin requests. For cookie-dependent endpoints, run the curl export with--cookiein your terminal. - OAuth flows and token refresh — no built-in login. Obtain the token however your service issues it and paste it into
Authorization; masking hides it on screen. - WebSocket, Server-Sent Events, long-polling — strictly request/response. Use a purpose-built client for streaming.
- Binary body preview — non-text responses (images, PDFs, protobuf) render as raw text. The content-type badge tells you what the server claimed; run the curl with
-o file.binto save real bytes.
Related tools
- Anthropic Messages API — purpose-built Claude playground with model picker, system prompt, streaming, and parameter sliders. Use when you want the full Claude request shape without hand-rolling headers.
- OpenAI Responses API — OpenAI Responses playground with conversation state, tool calls, and structured output. Use for API-specific affordances; fall back here for the raw wire format.
- URL Parser — break a URL into scheme, host, path, query, and fragment, or build one back up. Handy for constructing REST URLs with URL-encoded values before pasting them here.
- JWT Decoder — inspect the
Authorization: Bearer …token your API is returning or the one you pasted into a header here. Decodes header, payload, and signature with claim validation.
Frequently asked questions
Is my request actually sent from my browser, or proxied through your server?
The request is sent directly from your browser to the target server using the native `fetch()` API. Nothing is proxied, logged, or intercepted. You can verify this in your browser's devtools Network tab — the only outbound request you'll see is the one you sent. This means API keys, tokens, and bodies stay local; but it also means CORS applies, so some APIs will block browser-origin calls. For those, use the "Copy as curl" button and run the command from your terminal.
Why does my request fail with a CORS error when curl from my terminal works fine?
CORS (Cross-Origin Resource Sharing) is a browser-only restriction. Your terminal doesn't enforce it — it just sends the request. A browser will only make cross-origin requests to servers that opt in by returning an `Access-Control-Allow-Origin` header. Most modern APIs (GitHub, Stripe, Anthropic, OpenAI's newer endpoints) allow browser calls; many legacy APIs and internal services do not. When the request fails, click "Copy as curl" and run it in your terminal — same request, no CORS check.
Are my API keys stored anywhere?
No. Keys live only in the React state of the page, which means they vanish the moment you reload or close the tab. They are never written to localStorage, never sent to a server other than the one you're targeting, and never logged. Header fields with names like `Authorization`, `X-API-Key`, `Api-Key`, `Anthropic-Api-Key`, or `Openai-Api-Key` render with a `type="password"` input so screen-shares and shoulder-surfers don't accidentally capture the token.
Can I import a curl command I copied from browser devtools?
Yes. Open the "Paste a curl command" section, drop in the full command, and click "Import curl → request". The parser handles `-X`, `-H`, `-d`, `--data-raw`, `--data-binary`, `--data-urlencode`, `-u`, `-A`, `-e`, and the version flags `--http1.0`, `--http1.1`, `--http2`, `--http2-prior-knowledge`, `--http3`, and `--http3-only`. Multi-line commands with trailing `\` line continuations also parse cleanly. Flags that don't map to browser fetch — `--compressed`, `-k`, `-s`, `-L`, `-v`, `-i`, `-4`, `-6` — are silently ignored since the browser handles those concerns automatically.
Does the HTTP version selector actually force the browser to use HTTP/2 or HTTP/3?
No — and no other browser-based HTTP client can either. The `fetch()` API deliberately does not expose wire-protocol selection; the browser picks the version during the TLS handshake via ALPN negotiation (typically HTTP/3 when both sides speak it, then HTTP/2, then HTTP/1.1). The selector on this page changes only the emitted curl command, so "Copy as curl" with HTTP/2 selected gives you `curl --http2 …`. Use it when you need to reproduce a server bug that only shows up on a specific protocol version — run the generated curl in your terminal and you get exactly what you asked for.
Does the curl preview update as I type?
Yes. The curl preview panel sits directly above the paste area and re-renders every keystroke, with the output memoised so dragging through a 20-header list stays smooth. The Copy button on the preview reuses the same serializer as the "Copy as curl" action bar, so the clipboard can never drift from what you see on screen. The preview is shown as pretty multi-line curl by default (one flag per `\`-continued line), which is the format Stack Overflow answers and bug reports expect.
What methods does it support?
GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. GET and HEAD cannot carry request bodies (that's a fetch spec restriction, not ours), so the body input hides when those methods are selected. The full request, regardless of method, can be exported as curl or as a browser `fetch(...)` snippet with a single click. POST/PUT/PATCH/DELETE bodies are sent as raw text — JSON, form-urlencoded, XML, or whatever your endpoint expects — and the Content-Type header is yours to set.