JWT Decoder
Decode and inspect JSON Web Tokens with expiration checking.
Paste a curl command — the kind Chrome DevTools, Postman, or API docs hand you — and get clean JavaScript <code>fetch()</code> code. Headers, JSON bodies, form data, basic auth, cookies, and methods all translate. Useful when you're testing an API in curl and need to drop the call into a frontend, when porting Postman collections to code, or when copying a request from DevTools' "Copy as cURL" menu.
curl is the universal HTTP command-line client. fetch() is the universal JavaScript HTTP API. Every developer ends up moving requests between them constantly — testing an API call in curl from the terminal, then porting it into frontend code; pasting a curl command from API documentation and rewriting it for a service; copying a request from Chrome DevTools' "Copy as cURL" menu and turning it back into JavaScript. The two tools do the same thing but their argument shapes diverge in enough places to make hand-translation tedious.
The conversion is mostly mechanical. -X POST becomes method: "POST". -H "X-Foo: bar" becomes an entry in the headers object. A JSON body in -d becomes body: JSON.stringify(...). Where it stops being mechanical is the parts of HTTP that browsers handle differently than command-line clients: cookies (browser-managed via credentials: "include"), automatic decompression (browsers handle gzip themselves), and redirects (default behavior differs). This tool emits comments where the behavior changes, so you know what to verify.
The tool runs entirely client-side and parses curl with a tiny purpose-built shell-tokenizer — no eval, no server roundtrip, no third-party API. Paste a request with API keys or credentials in it and nothing leaves your browser. Useful when the request is from production logs and you want to reproduce it locally without exposing the data.
-X (method), -H (headers, repeatable), -d / --data / --data-raw / --data-binary (request body), --data-urlencode (form-encoded body), -F / --form (multipart form), -u (basic auth), -b / --cookie (cookies), -A / --user-agent, -e / --referer, -L (follow redirects, noted in output), --compressed (noted). Flags like -o, -w, --insecure, and --cacert are command-line-only concepts with no fetch() equivalent and are ignored with a note. Backslash line continuations and both single-quoted and double-quoted strings are parsed correctly.-d or --data, the tool inspects the body. If it parses as JSON, the output uses JSON.stringify(...) with the parsed value (cleaner than embedding the raw string) and sets a Content-Type: application/json header if you didn't supply one. If the body doesn't parse as JSON, it's passed through as a raw string. --data-urlencode is converted to a URLSearchParams body and the right Content-Type is added.--compressed — all handled. The resulting fetch() code will reproduce the same request with the same headers and body. Note that some headers Chrome adds automatically (Cookie, User-Agent, Accept-Encoding) are usually filtered out or supplied by the browser running your fetch() — you may want to remove them from the output to avoid duplicates.fetch() API, which is built into every modern browser, Node.js 18+, Deno, and Bun. For older Node.js (16 and below), install node-fetch and import it; the rest of the code is identical. The body construction (FormData, URLSearchParams, JSON.stringify) all uses standard objects available in both runtimes. Authentication via Basic auth uses btoa() in browser code — replace with Buffer.from(...).toString("base64") if you're targeting older Node specifically.-u user:pass) converts to an Authorization: Basic xxx header with the credentials base64-encoded. Bearer tokens (passed via -H "Authorization: Bearer ...") pass through as a header. Cookies (-b or --cookie) become a Cookie: header on the request. Note that browser fetch() does NOT send custom Cookie headers by default — for browser code you usually want to set credentials: "include" and let the browser manage cookies for the domain. The output flags this when relevant.