JWT Decoder
Inspect JWT header, payload and expiry.
About this tool
Decode a JSON Web Token to read its header and claims. Timestamps like exp, iat and nbf are shown as readable dates, and you can see at a glance whether the token has expired. The signature is not verified.
How to use it
- Paste a JSON Web Token. A leading “Bearer ” is removed automatically.
- Read the decoded header and payload.
- Check the status banner and the time claims to see when the token was issued and when it expires.
Questions
- Does this verify the signature?
- No. It only decodes the token. Verifying needs the secret or public key and should happen on your server. Never trust a token just because it decodes.
- Is it safe to paste a real token here?
- Decoding happens entirely in your browser and the token is never sent anywhere. Still, treat production tokens like passwords and prefer expired or test tokens when you can.
- What do exp, iat and nbf mean?
- exp is when the token expires, iat when it was issued, and nbf the moment before which it must not be accepted. All three are Unix timestamps in seconds.
- Can anyone read the contents of a JWT?
- Yes. The header and payload are only Base64url-encoded, not encrypted. Don’t put secrets or sensitive personal data in a JWT payload.
- Why does my token have five parts instead of three?
- A token with five dot-separated parts is a JWE, an encrypted JSON Web Token defined in RFC 7516. Its payload can’t be read without the decryption key, so this decoder reports an error. A token with only two parts was usually cut off when copied; even an unsigned token keeps a trailing dot.
- What is the kid in a JWT header?
- kid is the key ID. It tells the verifier which key to use when the issuer publishes several, for example in a JWKS document. This makes key rotation possible: new tokens are signed with a new key while tokens signed with the old one remain valid until they expire.
- Can I edit a JWT payload and still use it?
- You can change the payload and re-encode it, but the signature will no longer match, so a correctly configured server rejects the token. If an edited token is accepted, the server is not verifying signatures, which is a serious security hole worth reporting or fixing straight away.
What is a JWT and how is it structured?
A JSON Web Token, defined in RFC 7519, is a compact string of three parts separated by dots: header, payload and signature. The header says how the token is signed, with an alg value such as HS256 or RS256. The payload holds the claims: who the token is about (sub), who issued it (iss), who it is meant for (aud) and when it expires (exp). Both parts are JSON encoded with base64url.
The third part is the signature, computed over the first two with a secret or a private key. Because the header is JSON that begins with a brace and a double quote, almost every JWT starts with eyJ, which is how you can spot one in logs and request headers. Paste a token into this JWT decoder to see the header and payload formatted, with time claims shown as dates.
Why is my JWT rejected even though it decodes?
A token that decodes cleanly can still be refused, usually with a 401. The most common cause is expiry, so check the status banner, which tells you whether exp is already in the past. Remember that exp is in seconds: a backend that compares it with a JavaScript millisecond time will make the wrong call. Clock drift between servers matters too, which is why most libraries allow a small leeway.
If the times look right, compare the claims with what the server expects. An aud that doesn’t match the API, an unexpected iss, or a token from a staging identity provider sent to production all fail validation. A signature check fails when the key is wrong, the token was edited, or the alg in the header isn’t one the server accepts. This decoder doesn’t verify signatures, so it can’t tell you which of these applies.
HS256 vs RS256: which JWT algorithm to use
HS256 signs the token with HMAC-SHA256 and one shared secret. Every service that verifies tokens needs that same secret, which also lets it create new tokens. That is fine for a single backend but risky across many services. RS256 (RSA) and ES256 (ECDSA) use a key pair instead: the issuer signs with a private key, and everyone else verifies with the public key, often published at a JWKS endpoint.
Whichever you pick, fix the allowed algorithm on the verifying side instead of trusting the alg field in the header. A token with alg set to none carries no signature at all and must always be rejected. Keep exp short, minutes rather than days, and use refresh tokens for longer sessions. You can read alg and kid in the header panel here, and check any timestamp with the Unix Timestamp Converter.
Something not working, or a result looks wrong? Report a problem with this tool