Decode a JWT
Read the header and payload of a JSON Web Token. No key and no sign-up; the answer is never cached and the token is not written to the request log.
curl "https://agent-helper.org/decode/jwt?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzg5NTE2ODAwLCJleHAiOjE3OTg3NjE2MDB9.fCUF2mVctMBzAqgyX7qglyDzWJ00I2350DWkt8TCrSU"
header {"alg":"HS256","typ":"JWT"}
payload {"sub":"1234567890","name":"Jane Doe","role":"admin","iat":1789516800,"exp":1798761600}
# type: computed
# alg: HS256
# iat: 2026-09-16T00:00:00Z
# exp: 2027-01-01T00:00:00Z
# note: the signature was not verified; anyone can create a token with these contents
# note: this answer is never cached: not here, not by proxies (no-store, private)
# note: a token sent in a URL can still be recorded by proxies and logs along the way
The trap
A JWT is three base64url segments joined by dots. The first two are plain JSON: anyone can read them, and anyone can write them. The third is a signature over the first two, and it is the only part that gives the other two any meaning.
Decoding reads the first two segments and never looks at the third. A decoder will report that a token belongs to user 1234567890, carries the admin role and is valid until next year, even if somebody assembled that token by hand a minute ago without ever holding the signing key.
This matters because decoding looks like validation. The output is structured, it is plausible, and it arrives without an error. A forged token decodes exactly as a genuine one does, so there is nothing in the result to notice.
The failure lives in code that reads a claim and acts on it: comparing exp with the clock to decide whether a session is still alive, taking sub as the identity of the caller, reading a role to decide what to show. Each of those steps is safe after the signature has been checked with a key you control, and none of them is safe before.
The header deserves the same suspicion as the payload. It names the algorithm, and a token that declares alg as none has no signature at all. Libraries once accepted such tokens, or let an attacker switch a token from RSA to HMAC and sign it with the public key, and code that picks the algorithm from the token repeats that mistake.
Verification cannot happen here. It needs the signing key, or the public key and the list of algorithms you accept, and a signing key does not belong in a request to any web service, including this one.
What this endpoint does
The token is split at the dots, the header and payload are base64url-decoded and parsed as JSON, and both come back as they were. Every successful answer carries the note that the signature was not verified, and no parameter removes it. Time claims such as exp, iat and nbf are shown as dates beside the raw payload, without any judgement: the answer never says whether a token has expired or is valid, because without the key that statement would mean nothing. A malformed token gets a 400 saying which part failed and why.
Answers are served with no-store, private, so neither this service nor a proxy keeps them, and the token is not written to the request log. It still travels in a URL, and the answer says so. For verification, use a JWT library in your own code, with your own key.
Parameters
| Name | Required | Meaning and values | Default | Limit |
|---|---|---|---|---|
token | yes | JSON Web Token | — | 1024 bytes |
The whole path and query together are capped at 2048 bytes. Every parameter has the same meaning under /v1/decode/jwt.
Examples
A token that expired years ago
curl "https://agent-helper.org/decode/jwt?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsImV4cCI6MTU3NzgzNjgwMH0.IfNw86uVM9ugV9i__XIgPR7m_M4ao1ucOeX_U1GkcMU"
header {"alg":"HS256","typ":"JWT"}
payload {"sub":"42","exp":1577836800}
# type: computed
# alg: HS256
# exp: 2020-01-01T00:00:00Z
# note: the signature was not verified; anyone can create a token with these contents
# note: this answer is never cached: not here, not by proxies (no-store, private)
# note: a token sent in a URL can still be recorded by proxies and logs along the way
A token that declares no algorithm
curl "https://agent-helper.org/decode/jwt?token=eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiI0MiIsInJvbGUiOiJhZG1pbiJ9."
header {"alg":"none","typ":"JWT"}
payload {"sub":"42","role":"admin"}
# type: computed
# alg: none
# note: the signature was not verified; anyone can create a token with these contents
# note: this answer is never cached: not here, not by proxies (no-store, private)
# note: a token sent in a URL can still be recorded by proxies and logs along the way
A payload that is not valid JSON (error)
curl "https://agent-helper.org/decode/jwt?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMi.c2lnbmF0dXJl"
error: 400 bad parameter 'token'
parameter: token
problem: payload is not base64url-encoded JSON
[the rest of this error repeats the parameter list above]
Not a JWT at all (error)
curl "https://agent-helper.org/decode/jwt?token=abc"
error: 400 bad parameter 'token'
parameter: token
problem: a JWT has 3 dot-separated parts (5 for JWE); got 1
[the rest of this error repeats the parameter list above]
Limits and provenance
Rate class light (light computations: conversion, validation, dates, encodings, text, networks, geometry): 120 requests a minute per address, bursts of 30; wider limits apply per network and per autonomous system. Current values: /limits.
Answers are marked # type: computed; successful ones are served with Cache-Control: no-store, private.
Computed locally; no external data source is involved.
Related
- Encoding, hashing and tokens: Encode and decode base64, base64url, base32, base58, hex, percent-encoding and punycode; compute hashes and HMACs; decode JWTs. Byte counts in every answer.
- Data formats: Validate JSON with line and column, convert JSON, YAML, TOML and CSV, query with JSONPath, check JSON Schema, diff texts and test regular expressions safely.
- Time and dates: Current time, timezone conversion, date arithmetic, ISO weeks, cron and business days. Every answer carries the offset and the timezone rules it used.