JWT decoder

Paste a JSON Web Token to see its header and payload as JSON, its claims explained, when it expires, and whether the signature matches your secret. The token is decoded in your browser and never sent anywhere.

Paste the token on its own, with “Bearer ” in front, or the whole Authorization header. Spaces and line breaks are ignored.
The three parts

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzQyIiwiYXVkIjoiYXBpLmV4YW1wbGUuY29tIiwibmFtZSI6IkFkYSBMb3ZlbGFjZSIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE4OTM0NTYwMDAsImp0aSI6IjhmMTRlNDVmIn0.dIiLt5va8D9NnmTBLFJgkA2B88Y2c2dFuikbFPxsRjk

  • Header
  • Payload
  • Signature
Check the signature

Enter the secret the token was signed with to check it.

The secret is checked with your browser's WebCrypto and is never sent anywhere, like the token.

Status Checking the dates… From exp and nbf against your device's clock. A server may allow a minute or two of leeway.
Algorithm
HS256 HMAC with SHA-256: signed and checked with one shared secret
Type
JWT
Header
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload
{
  "iss": "https://auth.example.com",
  "sub": "user_42",
  "aud": "api.example.com",
  "name": "Ada Lovelace",
  "iat": 1767225600,
  "nbf": 1767225600,
  "exp": 1893456000,
  "jti": "8f14e45f"
}

Registered claims

  • iss Issuer
    https://auth.example.com

    Who made and signed the token, usually the login service's URL.

  • sub Subject
    user_42

    Who the token is about, usually a user ID.

  • aud Audience
    api.example.com

    Who the token is meant for. A server should reject a token whose audience is not itself.

  • exp Expires at
    1893456000

    After this moment the token must be rejected. Seconds since 1 January 1970 UTC.

  • nbf Not before
    1767225600

    Before this moment the token must be rejected. Seconds since 1 January 1970 UTC.

  • iat Issued at
    1767225600

    When the token was made. Seconds since 1 January 1970 UTC.

  • jti Token ID
    8f14e45f

    A unique ID for this token, so a server can block it or notice it being used twice.

JWTs guard the APIs and dashboards you run on your own servers. Looking for one to host them? From €3.02 a month today, among 2,226 servers.

Works in your browser: nothing you type is sent anywhere.

How a JWT works

A JSON Web Token (RFC 7519) is three pieces of text joined by dots. The header says how the token is signed, the payload holds the claims, such as who the user is and when the token expires, and the signature proves that both were made by someone with the key. Header and payload are JSON written in Base64url, a variant of Base64 that is safe in URLs.

header.payload.signature

header    = base64url(UTF-8 JSON, e.g. {"alg":"HS256","typ":"JWT"})
payload   = base64url(UTF-8 JSON with the claims)
signature = base64url(HMAC-SHA256(secret, header + "." + payload))

Base64url is an encoding, not encryption: anyone who has a token can read its payload, exactly as this page does, without any key. So never put passwords or other secrets in a JWT. What the key protects is the signature: change one character of the payload and the signature no longer matches.

With HS256, HS384 and HS512 the issuer and the server share one secret and sign with HMAC; this page can check those when you enter the secret. RS256, ES256 and the other public-key algorithms are signed with a private key and checked with the issuer's public key, which a server usually gets from a JWKS URL. Decoding a token is not the same as trusting it: a server must check the signature, the expiry and the audience.

Example

Take jwt.io's well-known example, eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c. The first part decodes to the header {"alg":"HS256","typ":"JWT"}: an HMAC-SHA256 signature. The second decodes to the payload {"sub":"1234567890","name":"John Doe","iat":1516239022}. Its iat of 1516239022 means it was issued on 18 January 2018 at 01:30:22 UTC, and with no exp it never expires. The last part is the 32-byte HMAC-SHA256 of the first two parts and the dot between them; with the secret your-256-bit-secret it matches, so the signature is valid.

The registered claims

ClaimWhat it means
iss · IssuerWho made and signed the token, usually the login service's URL.
sub · SubjectWho the token is about, usually a user ID.
aud · AudienceWho the token is meant for. A server should reject a token whose audience is not itself.
exp · Expires atAfter this moment the token must be rejected. Seconds since 1 January 1970 UTC.
nbf · Not beforeBefore this moment the token must be rejected. Seconds since 1 January 1970 UTC.
iat · Issued atWhen the token was made. Seconds since 1 January 1970 UTC.
jti · Token IDA unique ID for this token, so a server can block it or notice it being used twice.

Questions

Is it safe to paste my JWT here?

Yes. The token is decoded by JavaScript in your browser, and the signature is checked with your browser's built-in WebCrypto. Neither the token nor the secret is sent to a server or stored. Still treat a live token like a password: anyone who has it can use it until it expires.

Can a JWT be decoded without the secret?

Yes. The header and payload are only Base64url-encoded JSON, so anyone can read them without a key. The secret or public key is needed only to check that the signature is genuine. That is why a JWT must not contain passwords or other secrets.

How do I check if a JWT is expired?

Look at the exp claim: it is the expiry time in seconds since 1 January 1970 UTC. If the current time is past it, the token has expired. This page reads exp and nbf for you and shows the result as a date and as “expired 3 days ago” or “expires in 2 hours”.

What is the difference between HS256 and RS256?

HS256 signs with HMAC and one shared secret: whoever can check a token can also make one. RS256 signs with an RSA private key and is checked with the public key, so services can verify tokens without being able to issue them. RS256 or ES256 is the usual choice when several services check the same tokens.

Why is my JWT signature invalid?

The secret is wrong, it is Base64-encoded and needs the “Base64-encoded” option, or the token was changed after signing. Copying a token can also add or drop characters. If the token uses RS256, ES256 or another public-key algorithm, it cannot be checked with a secret at all: it needs the issuer's public key.