Skip to content
Everyday Utilities Free · No signup · Private · Instant results

JWT Decoder

Decode and inspect JSON Web Token headers and payloads per RFC 7519. Does NOT verify signatures.

About the JWT Decoder

The JWT Decoder on HT99 Tools splits a JSON Web Token (RFC 7519) into its three dot-separated parts, base64url-decodes the header and payload, and displays them as formatted JSON. It also surfaces the standard claims — sub, iss, iat, nbf, exp — with human-readable timestamps and an expiry check.

A JWT is a compact, URL-safe token format used for authentication in OAuth2, OpenID Connect, and many custom auth systems. The structure is always three Base64URL strings joined by dots: header.payload.signature. The header declares the algorithm and token type; the payload carries the claims (the actual data); the signature is a cryptographic MAC over the header and payload using the algorithm declared in the header.

Important: this tool decodes the header and payload only. It does not verify the signature. A JWT is encoded, not encrypted — the payload is readable by anyone who has the token, including an attacker who intercepts it. Authentication requires that the recipient cryptographically verify the signature with the issuer's public key (or shared HMAC secret) before trusting any claim in the payload.

How It Works

RFC 7519 §3 defines a JWT as three Base64URL-encoded parts separated by dots. The header (also called the JOSE header, defined in RFC 7515) declares the algorithm (alg) and token type (typ, usually JWT). The payload is a JSON object of claims — either registered claims (defined in RFC 7519 §4.1: iss, sub, aud, exp, nbf, iat, jti), public claims (registered in the IANA JWT registry), or private claims (agreed upon between parties).

The tool splits the token on ., expects exactly three parts, base64url-decodes each part (replacing - with +, _ with /, restoring = padding), and parses the result as JSON. The signature part is not decoded — it is an opaque byte string whose verification requires the issuer's key.

Registered time claims are expressed as NumericDate values (seconds since the Unix epoch, per RFC 7519 §2). The tool multiplies by 1000 to convert to milliseconds, then formats as an ISO 8601 string. The expiry check compares the current time to exp; the not-yet-valid check compares to nbf. Both checks are informational only — even if a token is not expired, the signature may be invalid.

Worked Examples

The default token decodes to a header of {"alg":"HS256","typ":"JWT"} and a payload of {"sub":"1234567890","name":"Ada Lovelace","iat":1735000000,"exp":1766544000,"iss":"ht99.icu"}. The tool reports that the token was issued on 2024-12-23, expires on 2025-12-23, and is currently valid (assuming the system clock is between those dates).

If the alg field is none (RFC 7519 explicitly allows this), the tool warns that the algorithm is dangerous. alg: none means the JWT is unsigned — the signature part is empty and anyone can forge a token with any payload. The CVE-2015-9235 vulnerability affected libraries that silently accepted alg: none when they should have rejected it; modern libraries refuse none unless explicitly enabled.

If you paste a token with a malformed signature (the third part is not a valid Base64URL string), the tool still decodes the header and payload — only the signature byte length is reported. This is intentional: the signature is opaque to the decoder and only the verifier can validate it.

When to Use This Tool

  • Inspecting the claims of an OAuth2 access token or OpenID Connect ID token during development.
  • Debugging authentication failures by checking exp, nbf, iss, and aud claims.
  • Confirming that the alg header matches what the server expected (a common cause of verification failures).
  • Demonstrating that a JWT payload is unencrypted and readable by anyone (a teaching point for security training).
  • Extracting the user ID, email, or roles from a JWT for client-side display before the API call completes.
  • Troubleshooting WWW-Authenticate error responses that quote the failed claim.
  • Inspecting a service-to-service token in a microservices architecture to verify the issuer.

Limitations & Disclaimer

This tool does not verify JWT signatures. Decoding a JWT reveals its payload to anyone; the security guarantee comes only from signature verification on the server. The tool does not support JWE (encrypted JWTs, which have five parts instead of three). It does not validate the kid header against a JWKS (JSON Web Key Set, RFC 7517). It does not enforce aud (audience) or iss (issuer) claims — those require knowing the expected values. The expiry check is informational: an unexpired token may still have an invalid signature, and an expired token may still be accepted by a clock-skew-tolerant server. See our disclaimer for full terms.

Frequently Asked Questions

Does the tool verify the JWT signature?

No. The tool decodes the header and payload only. To verify a JWT, you need the issuer's public key (for RSA/ECDSA) or the shared HMAC secret (for HS256), and a verification library such as <code>jsonwebtoken</code> for Node, <code>PyJWT</code> for Python, or <code>jose</code> for Go. The signature is a cryptographic MAC over the header and payload &mdash; without the key, you cannot confirm the token was issued by the claimed issuer.

Is a JWT encrypted?

By default, no. A standard JWT (technically a JWS &mdash; JSON Web Signature, RFC 7515) is encoded but not encrypted: the payload is readable by anyone who has the token. If confidentiality is required, use a JWE (JSON Web Encryption, RFC 7516), which encrypts the payload. JWE tokens have five parts instead of three and are visibly different. This tool does not decrypt JWE tokens.

What does alg: none mean?

RFC 7519 allows <code>alg: none</code>, which means the JWT is unsigned &mdash; the signature part is empty. This was intended for cases where integrity is provided by the transport (e.g. mTLS), but in practice it has been the source of multiple critical vulnerabilities (CVE-2015-9235, CVE-2022-21449). Modern libraries refuse <code>alg: none</code> unless explicitly enabled. Never accept <code>alg: none</code> tokens from untrusted sources.

What are the standard registered claims?

RFC 7519 §4.1 defines seven: <code>iss</code> (issuer), <code>sub</code> (subject), <code>aud</code> (audience), <code>exp</code> (expiration time), <code>nbf</code> (not before), <code>iat</code> (issued at), <code>jti</code> (JWT ID). The first three are strings; the next three are NumericDate values (seconds since epoch); the last is a unique identifier. Custom claims (e.g. <code>name</code>, <code>email</code>, <code>role</code>) are placed alongside these.

Why does the tool report an empty signature?

Because <code>alg: none</code> tokens carry an empty signature. The tool reports the byte length of the signature string (which is zero for <code>alg: none</code>) and explicitly flags <code>none</code> as dangerous. For signed tokens, the signature length depends on the algorithm: HS256 produces 32-byte signatures (43 Base64URL characters), RS256 produces 256-byte signatures (342 Base64URL characters).

Is my token uploaded anywhere?

No. Decoding runs entirely in the browser. JWTs you paste here &mdash; including those carrying access tokens or PII &mdash; never leave the device.

Last updated: September 9, 2026  ·  Author: HT99 Tools Editorial Team