Ttooleras
🎫

Decode and inspect JSON Web Token (JWT) headers, payloads, and signatures. Free, private — all processing in your browser.

Advertisement

Paste a JWT and this splits it into its three parts — header, payload, and signature — pretty-prints the JSON, lays out the standard claims (issuer, subject, expiry, and so on) in a table, and tells you at a glance whether the token has expired. If you have the signing secret, you can verify the signature too; and there's a create mode for minting test tokens.

Everything happens in your browser. That matters more than usual here: a JWT often carries real identity and session data, and this tool never sends it anywhere. One honest scope note — signature verification and creation here use HMAC (HS256/384/512); asymmetric algorithms (RS256, ES256) can be decoded and inspected but not verified without their public-key handling.

Step by step

  1. 1

    Paste the JWT

    Copy the full token (header.payload.signature) and paste it into the input field. Leading/trailing whitespace is trimmed.

  2. 2

    View decoded header

    The algorithm, token type, and any key identifier (kid) appear at the top. Look at `alg` to see how the token is signed.

  3. 3

    Inspect the payload

    All claims are decoded as JSON. Standard claims are explained; custom claims (like user roles, permissions, or app-specific fields) are shown verbatim.

  4. 4

    Check expiration

    The tool calculates whether `exp` is in the past or future and shows the human-readable date/time. Expired tokens are highlighted in red.

  5. 5

    Verify the signature externally

    This decoder cannot verify signatures (requires the issuer's key). Use a JWT library in your language of choice to verify, passing the correct secret (HS*) or public key (RS*/ES*/EdDSA).

Worked examples

Simple HS256-signed JWT

Standard JWT with user ID and name.

Input
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNzE0NTIxNjAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Output
HEADER: { "alg": "HS256", "typ": "JWT" }
PAYLOAD: { "sub": "1234567890", "name": "Jane Doe", "iat": 1714521600 }
SIGNATURE: (base64url-encoded HMAC-SHA256)

OAuth access token with scopes

Typical token from an OAuth 2.0 authorization server.

Input
eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyJ9.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzQyIiwiYXVkIjoiYXBpLmV4YW1wbGUuY29tIiwiZXhwIjoxNzE0NTI1MjAwLCJpYXQiOjE3MTQ1MjE2MDAsInNjb3BlIjoicmVhZDp1c2VyIHdyaXRlOnVzZXIifQ.sig
Output
HEADER: { "alg": "RS256", "kid": "abc123" }
PAYLOAD: {
  "iss": "https://auth.example.com",
  "sub": "user_42",
  "aud": "api.example.com",
  "exp": 1714525200,  ← expires in 1 hour
  "iat": 1714521600,
  "scope": "read:user write:user"
}

Expired token

Token whose exp claim is in the past is flagged.

Input
JWT with exp = 1714521600 (example)
Output
⚠️ EXPIRED
Expired 2 hours ago

Dangerous alg: none token

Unsigned tokens should always be rejected.

Input
eyJhbGciOiJub25lIn0.eyJhZG1pbiI6dHJ1ZX0.
Output
⚠️ SECURITY WARNING: alg "none" means no signature.
Any verifier accepting alg: none is vulnerable to forged tokens.

Firebase / Google ID token

OpenID Connect ID token from Google Identity.

Input
eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiJ1c2VyXzEyMyIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiSm9obiBEb2UifQ.sig
Output
HEADER: RS256, kid: 123
PAYLOAD: {
  "iss": "https://accounts.google.com",
  "sub": "user_123",
  "email": "user@example.com",
  "email_verified": true,
  "name": "John Doe"
}

Features at a glance

Decode JWT instantly

Paste any JWT — header, payload, and signature are decoded and displayed as formatted JSON in real-time.

Standard claims highlighted

Registered claims (iss, sub, aud, exp, iat, nbf, jti) are labeled and annotated. Expiration times are converted to human-readable dates.

Expiration check

Tokens that have expired or are not yet valid are flagged in red. See exactly how long until expiration or how long ago it expired.

Algorithm identification

The signing algorithm (HS256, RS256, ES256, EdDSA, none) is extracted from the header and documented.

Security warnings

Tokens using `alg: none` or weak algorithms are flagged. Missing critical claims (exp, aud) are highlighted.

Copy any section

Copy the decoded header, payload, or signature independently. Useful for debugging API responses and filing support tickets.

Dark mode JSON syntax highlighting

The decoded JSON is colorized for easy scanning — keys, strings, numbers, booleans all stand out.

100% client-side

Tokens never leave your browser. Safe for production access tokens, user sessions, and sensitive credentials.

Where this helps

Authentication debugging

  • Debug OAuth access tokens: When API calls fail, decode the access token to check which scopes are granted, who issued it, and when it expires.
  • Inspect OpenID Connect ID tokens: Read user identity claims (sub, email, name, picture) from the ID token returned by Google, Microsoft, Auth0, or Okta.
  • Troubleshoot refresh token flows: Refresh tokens are often JWTs with different claims (longer expiration, refresh-specific audience). Decode to verify structure.
  • Validate SSO integrations: SAML/OIDC assertions arrive as JWTs. Inspect the audience, issuer, and user attributes to debug integration issues.

API development

  • Test your own issued tokens: After generating a JWT on your backend, decode it to verify that the claims match what you intended.
  • Debug third-party API responses: Webhooks from Stripe, GitHub, etc. often include signed JWTs in headers — decode to see context.
  • Understand what an auth provider sends: Before writing JWT validation code, decode a few example tokens to see exactly what claims your auth provider includes.
  • Design token claims: Review existing tokens from similar apps to learn conventions for naming custom claims (role, tenant_id, plan, etc.).

Security review

  • Audit for alg: none vulnerability: Some JWT libraries accept `alg: none` tokens — a critical vulnerability allowing forged tokens. Check your tokens use strong algorithms and that your verifier rejects `none`.
  • Check signing algorithm strength: HS256 with a weak secret can be brute-forced. RS256 with a 2048-bit key is secure. ES256 and EdDSA are modern best practices.
  • Inspect claims for PII leaks: JWTs are not encrypted — anyone with the token can read the payload. Ensure you are not putting sensitive data like passwords, SSNs, or private emails in claims.
  • Verify expiration policy: Long-lived access tokens are a security risk. Most APIs should use short expirations (15 minutes to 1 hour) with refresh tokens.

Learning and education

  • Understand JWT structure: Decode example tokens to see how the header, payload, and signature are composed.
  • Compare JWT formats across providers: Decode tokens from different auth providers (Auth0, Firebase, AWS Cognito, Supabase) to see how they structure claims.
  • Debug JWT library integrations: When a JWT library rejects a token, decode it manually to see exactly what structure your library expects.

How it works

A JWT is three Base64URL parts joined by dots: header.payload.signature. The header says which algorithm signed it; the payload holds the claims; the signature is what makes it tamper-evident.

Decoding is not verifying — internalize this. The header and payload are just Base64URL, not encryption. Anyone who has the token can read every claim in it (try it — the payload shows in plain JSON here). Decoding tells you *what the token says*; only checking the signature tells you *whether to trust it*. This tool does both, but they're separate steps.

Standard claims the table decodes: iss (issuer), sub (subject/user), aud (audience), exp (expiry), nbf (not-before), iat (issued-at), jti (id). exp, nbf, and iat are Unix seconds; the tool converts them to readable dates and flags expiry against the current time.

Signature verification here recomputes the HMAC over header.payload with your secret and compares. A match means the token was signed with that exact secret and hasn't been altered. For RS256/ES256 (asymmetric), verification needs the issuer's public key and isn't performed here.

Pitfalls and fixes

Putting secrets in the payload

A JWT payload is Base64, not encrypted — anyone with the token reads it. Never store passwords, secret keys, or sensitive personal data in claims. Only put what you'd be comfortable showing the token holder.

Trusting a token because it decoded cleanly

Decoding always succeeds for well-formed tokens and proves nothing. You must verify the signature (and check exp) before trusting any claim. Decoding is inspection, not authentication.

The alg:none attack

Some libraries historically accepted alg:none (unsigned) tokens as valid. Always pin the expected algorithm server-side and reject none — never let the token dictate how it's verified.

Expecting expiry to be enforced automatically

exp is just a number in the payload; nothing enforces it unless your code checks it. This tool shows expiry status, but your backend must actually reject expired tokens.

Trying to verify an RS256 token with a secret

RS256/ES256 are asymmetric — they need the issuer's public key, not a shared secret. This tool verifies HMAC (HS*) tokens; for RSA/ECDSA, inspect the claims here but verify in your backend.

How it compares

Decode vs verify. Decoding is free and unauthenticated — it's just Base64. Verifying proves authenticity and requires the secret (HMAC) or public key (RSA/ECDSA). Never make a trust decision on a decoded-but-unverified token.

JWT vs a session cookie. A classic session cookie is an opaque ID that points at server-side state; the server can revoke it instantly. A JWT is self-contained — the server can validate it without a lookup, but *can't easily revoke* one before it expires. That trade-off (stateless and fast vs. revocable) is the core design choice.

HS256 vs RS256. HS256 signs and verifies with one shared secret — simple, but every verifier must hold the secret. RS256 signs with a private key and verifies with a public one, so you can hand out the public key freely. Use RS256 when multiple independent services need to verify tokens they didn't issue.

Questions and answers

Is my token uploaded when I paste it?

No. Decoding, verification, and creation all run in your browser via the Web Crypto API. Nothing is sent to a server, which is why it's safe to inspect a real token here.

Is a JWT encrypted?

No. The header and payload are Base64URL-encoded, not encrypted — anyone with the token can read every claim. That's exactly why you must never put secrets in a JWT payload.

Does decoding a token mean it's valid?

No. Any well-formed token decodes. Validity requires verifying the signature with the correct secret or key and checking the expiry. Decoding shows what the token claims; verification shows whether to believe it.

Can it verify RS256 or ES256 tokens?

It can decode and inspect them, but signature verification here covers HMAC (HS256/384/512) only. Asymmetric algorithms need the issuer's public key — verify those in your backend.

What are the three parts of a JWT?

Header (which algorithm and token type), payload (the claims — who the token is about, when it expires, custom data), and signature (an HMAC or asymmetric signature over the first two parts that detects tampering).

Is it safe to paste a production token here?

The tool is fully client-side, so it isn't transmitted. Still treat any live token as sensitive — anyone who sees your screen or clipboard could reuse it until it expires.

Additional resources

Advertisement

Learn more

Explore more tools

200+ free tools that run in your browser.

Browse all tools →