JWT Decoder

This JWT decoder splits a JSON Web Token into its header, payload and signature and shows the claims as readable JSON. Expiry (exp), issued-at (iat) and not-before (nbf) times are converted to dates, and you can see at a glance whether the token has expired. It decodes only; it does not verify the signature.

Decode only: the signature is not verified

Anyone can read a JWT, so a decoded payload proves nothing on its own. Decoding happens in your browser and the token is never sent, but avoid pasting live production tokens into any website.

eyJhbGciOiJIUzI1NiIsInR5….eyJzdWIiOiIxMjM0NTY3ODkw….k3Q7u0sS8m2XJ4o5…

alg: HS256 · typ: JWT

Header

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

Payload

{
  "sub": "1234567890",
  "name": "Ada Lovelace",
  "role": "admin",
  "iss": "https://auth.example.com",
  "aud": "api",
  "iat": 1700000000,
  "exp": 1900000000
}
Time claims
ClaimValueDate (UTC)Relative
iat Issued at17000000002023-11-14T22:13:20.000Z…
exp Expires19000000002030-03-17T17:46:40.000Z…
Registered claims (RFC 7519)
subSubject: the user or entity the token is about"1234567890"
issIssuer: who created the token"https://auth.example.com"
audAudience: who the token is meant for"api"
iatIssued at1700000000
expExpiration time1900000000

Signature (not verified)

k3Q7u0sS8m2XJ4o5vG3a1b2c3d4e5f6g7h8i9j0k1lM

32 bytes. Checking it needs the secret or public key for the HS256 algorithm, which should be done by your server or a JWT library.

Decoded locally in your browser. The token is never sent or stored.

How does JWT decoding work?

Decoding a JWT means splitting it at the two dots and Base64URL-decoding the first two parts, which are plain JSON: the header and the payload. No key is needed, because a signed JWT is not encrypted, only protected against changes. That is also why a decoded token must not be trusted until a server has verified its signature with the right key.

How to decode a JWT token

  1. Paste the token and the JWT decode runs as you type. A full Authorization: Bearer eyJ… header works too: the prefix is removed for you, which makes it a quick bearer token decoder.
  2. Read the header (algorithm, type, key ID) and the payload claims, each formatted and ready to copy. The JWT parser checks that every part is valid Base64URL and JSON, so a mistyped token is reported instead of half-decoded.
  3. Check the status badge and the time claims table to see when the token was issued and when it expires, in UTC and relative to now.
  4. Look at any warnings: an alg of none, time claims in milliseconds instead of seconds, or the wrong Base64 alphabet.

The three parts of a JWT

A signed JWT uses the JWS compact format from RFC 7515: header.payload.signature, each part encoded with Base64URL without padding.

eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiIxMjMifQ . 3q2-7zk…
└──── header ──────┘   └─── payload ───┘   └ signature ┘
{"alg":"HS256"}        {"sub":"123"}       HMAC or RSA/ECDSA bytes

The signature is computed over the first two parts, so changing a single character of the header or payload makes it invalid. A token with five parts is a JWE: its payload is encrypted and cannot be decoded without the key, so this tool reports that instead of guessing.

Registered claims

RFC 7519, section 4.1 defines a small set of standard claim names. All are optional, and applications add their own claims, such as name, email or scope, alongside them.

ClaimMeaning
issIssuer: who created the token
subSubject: the user or entity the token is about
audAudience: who the token is meant for
expExpiration time
nbfNot valid before
iatIssued at
jtiJWT ID: unique identifier

exp, nbf and iat are NumericDate values: seconds since the Unix epoch, not milliseconds. The epoch converter turns any of them into a date. A token is expired when the current time is at or after exp; servers often allow a minute or two of clock skew.

Decode vs. verify, and “JWT decrypt”

Decoding is reading; verifying is proving the token came from the issuer and was not changed. Verification needs the shared secret (for HS256) or the issuer's public key (for RS256, ES256 and similar) and should happen on your server with a maintained JWT library, which also checks exp, aud and iss. People sometimes search for a “JWT decrypt” tool, but a normal signed JWT is not encrypted at all: its payload is just Base64URL text that the Base64 decoder can read too. Only JWE tokens are encrypted.

Because the payload is readable by anyone holding the token, never put passwords or other secrets in JWT claims, and treat tokens themselves as secrets. This JWT debugger runs entirely in your browser and sends nothing, but production tokens are still best inspected with local tools.

Frequently asked questions

What is JWT?

JWT is a compact, URL-safe format for sending a set of claims, such as a user ID and an expiry time, between two parties, defined in RFC 7519. It is most often used as an access token or ID token after login: the server signs it, and APIs check the signature instead of looking up a session.

What is a JSON Web Token?

A JSON Web Token is the full name of a JWT: three Base64URL-encoded parts separated by dots, a JSON header, a JSON payload of claims and a signature. The header names the signing algorithm (for example HS256 or RS256), and the signature lets the receiver detect any change to the header or payload.

What is a JWT token?

A JWT token is a JSON Web Token used as a credential, usually sent in an Authorization: Bearer header to prove who the caller is and what they may do. It is a bearer token, so anyone holding it can use it until it expires, which is why it should be short-lived and only sent over HTTPS.

What does JWT stand for?

JWT stands for JSON Web Token, and RFC 7519 says it is pronounced like the English word "jot". It belongs to the JOSE family of standards, together with JWS (signatures), JWE (encryption) and JWK (keys).

How to decode JWT token?

To decode a JWT token, paste it into the decoder above and the header and payload appear as formatted JSON, with exp, iat and nbf shown as dates. Manually, split the token at the dots and Base64URL-decode the first two parts; in JavaScript, JSON.parse(atob(token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"))) reads an ASCII payload.