internettoolbox
← Back to Tools

JWT Decoder

How it works

Paste any JWT, the long xxx.yyy.zzz string you find in Authorization: Bearer headers, OAuth responses, cookies or Firebase auth tokens. The tool splits it into its three parts (header, payload, signature), Base64URL-decodes the first two into JSON, and lays them out side-by-side with syntax highlighting. The third part is shown as-is, because a signature is binary, not decodable text.

The header tells you which algorithm signed the token (alg) and sometimes which key was used (kid). Common values: HS256 (HMAC-SHA-256, symmetric), RS256 (RSA-SHA-256, asymmetric, the default for OAuth / OpenID Connect), ES256 (ECDSA P-256, what Apple and modern issuers prefer), and the infamous "none", which means unsigned and should always be rejected.

The payload carries the claims, the actual data inside the token. Standard claims the tool highlights: • `iss`: issuer (which service minted the token) • `sub`: subject (usually the user ID) • `aud`: audience (which service is allowed to consume it) • `exp`: expiration, a Unix timestamp; the tool converts it to a human date and an "expires in 23 minutes" badge, or "EXPIRED 2 hours ago" if it is past • `iat`: issued-at timestamp • `nbf`: not-before (the token is not valid before this time) • `jti`: a unique token ID, used to revoke individual tokens

Everything else is a custom claim (roles, permissions, tenant ID, email). The tool preserves the exact JSON key order and types, so you can eyeball what your auth server is actually emitting.

Security note worth taking seriously: do NOT paste a production JWT into an online tool you don't control. JWTs can contain PII (email, user ID), session identifiers and access scopes. Even a read-only tool that sends the token to a server has just received, logged and possibly stored your credentials. This tool decodes inside the page, which you can confirm in DevTools → Network by watching no request fire, but for production debugging prefer the `jwt` CLI or a local IDE extension where you can.

Frequently Asked Questions

Is it safe to paste my JWT here?

Safer than most online decoders, because this one runs entirely in your browser: pasting and decoding fire no network request, which you can confirm in DevTools → Network. That said, for production tokens carrying an active session identifier the safest route is always a local CLI or your IDE's JWT extension. Any valid token pasted into any web page is a potential credential leak if the page or a browser extension is compromised.

Does it verify the signature?

No, this tool only decodes. Signature verification needs the signing secret (HS256) or the issuer's public key (RS256 / ES256), and neither belongs in a random web tool. Decoding is one-way reading; verification is a separate step, best done server-side or with a dedicated library (jose, jsonwebtoken, pyjwt).

What claims are shown?

Every claim in the payload, with special highlighting for the standard registered ones: iss (issuer), sub (subject), aud (audience), exp (expiration, rendered as a human date plus an expires-in badge), iat (issued-at), nbf (not-before), jti (token ID). Custom claims (roles, tenant, email, scopes) are listed below in their original order.

Why does my token look like it has three parts separated by dots?

Because a JWT has exactly three parts: header.payload.signature, each Base64URL-encoded. The header and payload decode to JSON; the signature is a binary MAC or signature that cannot be decoded to readable text. If your token has more or fewer dots it is not a standard JWT, possibly a JWE (the encrypted variant, which this tool does not support).

My JWT has "alg":"none", is that dangerous?

Yes, historically a major vulnerability. alg:none means the token is unsigned, and any application that accepts it blindly will trust forged tokens. Modern libraries reject alg:none by default. Seeing it in a token from a production service is a red flag: the issuer should never emit unsigned tokens.

What's the difference between HS256 and RS256?

HS256 is symmetric (HMAC with a shared secret): fast, but anyone who can verify can also sign. RS256 is asymmetric (an RSA key pair): the issuer signs with the private key and consumers verify with the public key. OAuth and OpenID Connect use RS256 (or ES256) precisely because the public key can be distributed safely. Use HS256 only for internal same-service tokens where a shared secret makes sense.

How do I check if my JWT is expired?

Read the badge: green "expires in 23 minutes" while the token is still valid, red "EXPIRED 2 hours ago" once it is not. The badge comes from the `exp` claim, a Unix timestamp in seconds, and the token is expired when `exp < Date.now() / 1000`. A token with no `exp` claim never expires, which is usually a misconfiguration since most issuers should set one.

Can I decode a JWT in Node, Python, or with curl?

Yes, in one line each. Node: `Buffer.from(token.split('.')[1], 'base64url').toString()`. Python: `import base64,json; json.loads(base64.urlsafe_b64decode(token.split('.')[1] + '=='))`. Bash: `echo $TOKEN | cut -d. -f2 | base64 -d | jq` (add `=` padding if needed). All three decode the payload only; for verification use jose (Node), pyjwt (Python) or a CLI like jwt-cli.

What's the difference between JWT and JWE?

A JWT (JSON Web Token, RFC 7519) is signed: the payload is Base64-encoded and readable by anyone, since signing only proves who issued it. A JWE (JSON Web Encryption, RFC 7516) is encrypted: the payload is unreadable without the decryption key. JWTs have three parts (header.payload.signature), JWEs have five (header.encryptedKey.iv.ciphertext.tag). This tool decodes JWTs only; a JWE needs the recipient's private key and cannot be opened by a generic web tool.

JWT signing algorithms: what to use and when

The `alg` field in a JWT header tells you how the token was signed. Quick reference for the algorithms you'll encounter in production tokens.

algTypeKey materialTypical useNotes
HS256HMAC-SHA-256 (symmetric)Shared secret ≥ 32 bytesInternal same-service tokens, single-tenant appsFast. Anyone who can verify can also sign, so never distribute the secret
HS384HMAC-SHA-384 (symmetric)Shared secret ≥ 48 bytesSame as HS256 with stronger hashRare. HS256 is sufficient for almost all cases
HS512HMAC-SHA-512 (symmetric)Shared secret ≥ 64 bytesHigh-security symmetric tokensRare
RS256RSA-PKCS1-v1_5 + SHA-256RSA key pair (2048-bit minimum)OAuth 2.0, OpenID Connect, public-facing APIsDefault for Auth0, Okta, AWS Cognito, Firebase. Public key can be shared via JWKS
RS384RSA-PKCS1-v1_5 + SHA-384RSA 2048+As RS256 with stronger hashLow adoption
RS512RSA-PKCS1-v1_5 + SHA-512RSA 2048+As RS256 with stronger hashLow adoption
ES256ECDSA P-256 + SHA-256EC P-256 key pairModern OAuth, mobile apps, Apple Sign InSmaller signatures (64 bytes vs RSA's 256+). What most modern issuers prefer
ES384ECDSA P-384 + SHA-384EC P-384 key pairHigh-security ECDSALow adoption
ES512ECDSA P-521 + SHA-512EC P-521 key pairVery-high-security ECDSALow adoption
EdDSAEd25519 (or Ed448)32-byte Ed25519 keyNewer alternative to ECDSA: fast, constant-timeGrowing adoption. Supported by jose, jsonwebtoken (with plugins), pyjwt 2.6+
PS256RSA-PSS + SHA-256RSA 2048+More secure RSA padding than RS256Recommended over RS256 by some specs (FAPI). Verify your library supports it
none(unsigned)(none)Debugging onlyNEVER accept in production: historical major vulnerability (CVE-2015-9235). Reject explicitly

Defined by RFC 7518 (JOSE / JWA). Most identity providers default to RS256; modern stacks (Apple, Firebase, newer Auth0 apps) increasingly use ES256 or EdDSA for smaller tokens and better mobile performance.

Tool switcher

Search and jump to any tool