WebPeeks
RFC 7519

JWT decoder

Paste a JSON Web Token to see its header and claims, with timestamps converted to dates and the common mistakes pointed out. Decoding happens in this page; nothing is sent anywhere.

Do not paste production tokens into websites. This page sends nothing, but a valid token works like a password until it expires. Use a test token, an expired one, or one from a development environment. The signature is decoded, never verified.

A leading "Bearer " is removed automatically.
  • Warn
    Expired 12 days ago

    A correct server rejects it. Note that this is judged by your device's clock.

  • Info
    HS256: HMAC with SHA-256 (shared secret)

    Whoever can verify an HMAC token can also create one, because the same secret does both. Fine inside one service; for tokens checked by several parties, an asymmetric algorithm (RS256, ES256, EdDSA) is safer. The secret needs to be long and random: short secrets can be brute-forced offline from any captured token.

Header

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

Payload

{
  "iss": "https://auth.example.com",
  "sub": "user_8431",
  "aud": "api.example.com",
  "iat": 1790000000,
  "exp": 1790003600,
  "scope": "read:orders write:orders",
  "email": "jane@example.com"
}

Claims explained

Claims
iss — Issuer: who created and signed the tokenhttps://auth.example.com
sub — Subject: who the token is about, usually a user IDuser_8431
aud — Audience: who the token is meant for; others must reject itapi.example.com
iat — Issued at1790000000 → 2026-09-21 14:13:20 UTC (12 days ago)
exp — Expires at1790003600 → 2026-09-21 15:13:20 UTC (12 days ago)
scope — Permissions granted (OAuth 2.0)read:orders write:orders
email — Email addressjane@example.com

Signature

32 bytes. Not verified. Checking it needs the issuer's key; do that in your own code with a maintained JWT library, never by trusting a decoder.

How a JWT is put together

A JSON Web Token (RFC 7519) in its usual signed form is three base64url-encoded parts joined by dots: header.payload.signature. Base64url is ordinary base64 with - and _ in place of + and /, and no padding, so the token is safe in URLs and headers. The header and payload are JSON; the signature is raw bytes computed over the first two parts exactly as they appear, dots included. An encrypted token (JWE) has five parts instead, and its payload cannot be read without the key.

Decoding is just the reverse of that encoding. This page splits the token, decodes each part, parses the JSON, and then reads the claims. Dates in JWTs are NumericDate values: whole seconds since 1 January 1970 UTC, not milliseconds.

The registered claims

ClaimNameWhat a server should do with it
issIssuerAccept only issuers it trusts
subSubjectIdentify the user or client
audAudienceReject tokens not meant for it
expExpiration timeReject after this moment, allowing a little clock skew
nbfNot beforeReject before this moment
iatIssued atOptional age limits
jtiJWT IDDetect a token being replayed

Signing algorithms

The alg header names one of the algorithms in RFC 7518 (JWA) or RFC 8037. The practical split is between symmetric HMAC (the HS family), where one shared secret both signs and verifies, and asymmetric signatures, where a private key signs and anyone with the public key can verify.

algMeaning
HS256HMAC with SHA-256 (shared secret)
HS384HMAC with SHA-384 (shared secret)
HS512HMAC with SHA-512 (shared secret)
RS256RSA PKCS#1 v1.5 with SHA-256
RS384RSA PKCS#1 v1.5 with SHA-384
RS512RSA PKCS#1 v1.5 with SHA-512
PS256RSA-PSS with SHA-256
PS384RSA-PSS with SHA-384
PS512RSA-PSS with SHA-512
ES256ECDSA P-256 with SHA-256
ES384ECDSA P-384 with SHA-384
ES512ECDSA P-521 with SHA-512
EdDSAEdDSA (usually Ed25519)
noneNo signature

A worked example

The example token's header is {"alg":"HS256","typ":"JWT"}. Its payload says it was issued by https://auth.example.com for user user_8431, to be used by api.example.com, with the scopes read:orders write:orders.

iat is 1790000000, which is 2026-09-21 14:13:20 UTC, and exp is 1790003600, exactly 3,600 seconds (one hour) later. That is a typical access-token lifetime, and it means the token has long since expired: any correct server would reject it now. The algorithm is HS256, so the API that checks it must hold the same secret as the issuer; for a token accepted by several services an asymmetric algorithm such as ES256 or RS256 would keep the ability to create tokens in one place.

What decoding cannot tell you

Whether the token is genuine. Anyone can write a token with any claims they like; only checking the signature with the right key, and then checking iss, aud, exp and nbf, establishes that it is real and current. Expiry on this page is judged by your device's clock. Claims beyond the registered ones are explained where they are widely used (OAuth scopes, OpenID Connect profile claims), but their meaning is ultimately whatever the issuer decided.

Common questions

Is it safe to paste a token here?

Nothing leaves your browser: the page makes no network request when you paste, which you can confirm in the Network tab of the developer tools. Even so, a live token is a password for as long as it is valid, so the habit worth having is to decode test tokens or expired ones, and not paste production tokens into any website, this one included.

Why is the signature not verified?

Verifying needs the key: the shared secret for HS256, or the issuer's public key for RS256 and ES256. A decoder that asked for your secret would be asking you to paste the one thing that must stay private. Verify in your own code with a maintained JWT library, which also checks exp, nbf, iss and aud for you.

Can anyone read the contents of a JWT?

Yes. A normal signed JWT (JWS) is base64url-encoded, not encrypted; anyone holding it can read every claim, as this page shows. The signature only proves nobody changed it. If the contents must be secret, use an encrypted JWT (JWE, five parts instead of three) or keep the data on the server.

What is the difference between an ID token and an access token?

In OpenID Connect, the ID token is a JWT for the client application, describing who logged in (sub, email, name) and it should not be sent to APIs. The access token is for calling APIs; it may or may not be a JWT, and the client should treat it as opaque. If you can decode an access token, that is a detail of the provider, not something to depend on.

What does "alg: none" mean and why is it dangerous?

It declares that the token has no signature. RFC 7519 allows such "unsecured" tokens, but a server that accepts them lets anyone forge a token by editing the payload and deleting the signature. Several JWT libraries shipped with exactly this flaw around 2015; modern ones reject alg=none unless explicitly told otherwise.