Skip to content

What’s inside a JWT, and is it safe to decode one?

A JWT looks scrambled, but most of it is plain JSON that anyone can read. Here is what each part means and how to inspect a token without leaking it.

By Ali Raza · Published

Three parts, separated by dots

This is a complete JWT, signed with the secret example-secret:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQyIiwibmFtZSI6IkFkYSBMb3ZlbGFjZSIsImlhdCI6MTc2NzIyNTYwMCwiZXhwIjoxNzY3MjI5MjAwfQ.A7UhKa4T-XotS2A64vUN6FfQ496oqPotU5k41hreECc

It is three pieces of base64url text joined by dots: header, payload and signature. Base64url is Base64 with - and _ in place of + and /, and without padding (RFC 7515). It is an encoding, not encryption, so the first two parts decode straight back to JSON:

{ "alg": "HS256", "typ": "JWT" }

{
  "sub": "user-42",
  "name": "Ada Lovelace",
  "iat": 1767225600,
  "exp": 1767229200
}

The header says how the token is signed, here with HMAC-SHA256. The payload holds the claims: statements about the user or session. The third part is the signature, computed over the first two.

What the standard claims mean

RFC 7519 registers seven claim names. All are optional; apps add their own, such as name or role.

iss
Issuer: who created the token.
sub
Subject: who it is about, usually a user ID.
aud
Audience: who it is meant for.
exp
Expiration time: the token must not be accepted after it.
nbf
Not before: it must not be accepted earlier.
iat
Issued at: when it was created.
jti
JWT ID: a unique identifier for the token.

The times are “NumericDate” values: seconds since January 1, 1970, UTC. In the example, iat 1767225600 is January 1, 2026, 00:00 UTC and exp is one hour later. The Unix Timestamp Converter turns such numbers into dates.

Decoding is not verifying

Anyone can decode a JWT; no secret is needed. That is why a payload must never hold passwords or other secrets. What the secret or key gives you is verification: recomputing the signature proves that the token was issued by someone holding the key and that nobody changed a single character since.

  • HS256, HS384, HS512 use one shared secret to sign and verify.
  • RS, PS, ES and EdDSA sign with a private key and verify with the matching public key, which can be shared openly.
  • A token with "alg": "none" has no signature at all. RFC 8725 tells applications to accept only the algorithms they expect, so a token can’t choose a weaker check for itself.

A valid signature doesn’t make a token current. Expiry is a separate check against exp and nbf, which the receiving application must do too.

Is it safe to paste a token into a website?

A JWT is usually a bearer credential: whoever holds it can act as you until it expires. Pasting a live token into a site that sends it to a server hands that power to the server, its logs and anyone who can read them.

  • Prefer a decoder that works locally. The JWT Decoder runs in your browser and makes no network request with the token; you can check this in the developer tools’ Network tab.
  • Decode copies of tokens from test systems when you can, rather than production tokens.
  • If a production token was exposed, revoke it or let it expire, and sign in again for a new one.

Decoding a token by hand

To read a payload without any JWT tool, take the middle part, the text between the two dots, and decode it as Base64 with the URL-safe alphabet. The Base64 Encode & Decode tool accepts base64url and missing padding, so you can paste the part as it is.

Sources

  1. RFC 7519: JSON Web Token (JWT), IETF
  2. RFC 7515: JSON Web Signature (JWS), IETF
  3. RFC 8725: JSON Web Token Best Current Practices, IETF