Skip to content

What a JWT Actually Contains

Sep 2, 2026 · Formats & Standards

A JWT is three base64url-encoded parts joined by dots, header.payload.signature, and the header and payload are merely encoded, not encrypted, so anyone holding the token can read them; only the signature is protected. That single fact, that a JWT is readable rather than secret, explains most of how they are used correctly and most of how they are misused. This article breaks a token into its three parts, lists the standard claims, and draws the line between decoding a token and verifying it.

What are the three parts of a JWT?

A JWT (JSON Web Token) is a single string with exactly two dots dividing it into three segments. A token looks like this, shortened for space:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0Iiwibm.4pcPyMD09olPSyXnrXCjTwXyr4

Split on the dots and you get three parts, each independently base64url-encoded:

  1. Header — a small JSON object describing the token type and the signing algorithm.
  2. Payload — a JSON object holding the claims, meaning the actual data the token asserts.
  3. Signature — bytes that prove the header and payload were not altered after signing.

The first two decode straight back to readable JSON. The third is a cryptographic value, not readable text. Pasting a token into a client-side JWT decoder shows all three decoded at once, which is the quickest way to see this structure for yourself.

What does base64url encoding mean here?

Base64url is a URL-safe variant of base64, and it is an encoding, not encryption. Standard base64 uses the characters + and / and pads the end with =, none of which are safe inside a URL or an HTTP header. Base64url swaps + for -, swaps / for _, and drops the padding, so the token survives being placed in a query string, a cookie, or an Authorization header untouched. The crucial consequence is reversibility: because base64url is a plain transformation, anyone can decode the header and payload back to JSON without any key. Encoding hides nothing; it only makes the bytes safe to transport.

What is in the header?

The header is a JSON object that tells the recipient how to process the token. A typical header decodes to:

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

The alg field names the signing algorithm, such as HS256 for HMAC with SHA-256, or an asymmetric algorithm like RS256 for RSA with SHA-256. The typ field is conventionally JWT. Some tokens add a kid, a key identifier that tells the verifier which key to use when the issuer rotates keys. The header matters for security because the verifier must decide which algorithm to trust rather than blindly obeying alg.

What is in the payload?

The payload holds the claims, which are the statements the token makes, typically about who the user is and how long the token is valid. Claims come in three kinds: registered claims defined by the specification, public claims used by convention, and private claims your own application defines. A decoded payload might read:

{
  "iss": "https://auth.example.com",
  "sub": "1234567890",
  "aud": "https://api.example.com",
  "iat": 1735689600,
  "nbf": 1735689600,
  "exp": 1735693200,
  "role": "editor"
}

Here role is a private claim, while the rest are registered claims. This table lists the standard registered claims you will see most often:

Claim Name Meaning
iss Issuer Who created and signed the token.
sub Subject Who the token is about, usually a user ID.
aud Audience Who the token is intended for, such as a specific API.
exp Expiration Time After this time the token must be rejected.
nbf Not Before Before this time the token must not be accepted.
iat Issued At When the token was created.
jti JWT ID A unique identifier, useful for revoking a specific token.

The three time claims, exp, nbf, and iat, are all NumericDate values: seconds elapsed since the Unix epoch of 1970-01-01 UTC. A value like 1735693200 is an integer count of seconds, not a date string, which is why a decoder often shows it translated into a human-readable time.

What is the signature and what does it protect?

The signature is computed over the encoded header and payload together, and it proves integrity, not secrecy. For an HMAC algorithm like HS256, the signer computes HMAC-SHA256(base64url(header) + "." + base64url(payload), secret) and base64url-encodes the result as the third part. Because the signer needs the secret and any change to the header or payload changes the signature, a recipient who also knows the secret can recompute the signature and confirm the token is authentic. For asymmetric algorithms like RS256, the issuer signs with a private key and anyone can verify with the matching public key. What the signature does not do is hide the contents: it seals the token against tampering while leaving the header and payload fully readable.

Is the payload encrypted?

No. This is the single most important and most misunderstood point about JWTs: a standard signed JWT is not encrypted at all. The header and payload are only base64url-encoded, so anyone who intercepts or is handed the token can decode and read every claim inside it. The signature stops them from altering the token without detection, but it does nothing to conceal what the token says. The practical rule follows directly: never put anything sensitive in a JWT payload. No passwords, no API secrets, no private personal data that would cause harm if read. Put only claims you are comfortable being visible to anyone who holds the token, and protect the token itself in transit and at rest. There is a separate standard for encrypted tokens, JWE, but the ordinary JWT you meet in an Authorization: Bearer header is signed and readable, not encrypted.

What is the difference between decoding and verifying?

Decoding reads a token; verifying trusts it, and only verification establishes security. Decoding simply base64url-decodes the header and payload back to JSON, needs no key, and can be done by anyone, including an attacker. Verifying recomputes the signature using the secret or the issuer’s public key and confirms it matches the token, which proves the token was issued by whoever holds the signing key and has not been modified. A real verification step then also checks the claims: that exp is in the future, that nbf has passed, that iss is the expected issuer, and that aud names this service. A decoder that shows you the contents is an inspection tool, not an authentication check; your server must always verify, never merely decode, before trusting a token’s claims.

How do you inspect a JWT safely?

Inspect tokens in a decoder that runs entirely in your browser, because a JWT is a live credential. While the payload is not secret in the cryptographic sense, the token as a whole often grants access, so pasting a production token into a remote website means handing a working credential to a third party. A client-side JWT decoder parses the three parts locally, shows the header and payload as formatted JSON, translates the timestamp claims into readable dates, and keeps the token on your machine. That local-only handling lets you debug a real token, confirm its claims and expiry, and understand exactly what it contains without ever transmitting the credential itself.

Once you internalise the shape, JWTs stop being mysterious: three dot-separated base64url parts, a readable header and payload, and a signature that seals but does not hide. Treat the payload as public, always verify before trusting, and keep sensitive data out of it entirely.

Frequently asked questions

Is a JWT encrypted?

No, not a standard signed JWT. The header and payload are only base64url-encoded, which is reversible, so anyone holding the token can read their contents. The signature protects against tampering, not against reading.

What does base64url encoding do?

It represents binary or text data using URL-safe characters, using minus and underscore instead of plus and slash and dropping the trailing equals padding. It is an encoding, not encryption, so it can be decoded by anyone.

What is the difference between decoding and verifying a JWT?

Decoding just base64url-decodes the parts to read them and requires no key. Verifying recomputes the signature with the secret or public key to confirm the token is authentic and unaltered, and it is the step that actually establishes trust.

What do iss, sub, exp, and iat mean?

They are registered claims: iss is the issuer, sub is the subject the token is about, exp is the expiry time, and iat is the time the token was issued. All time claims are seconds since the Unix epoch.

Should I put sensitive data in a JWT payload?

No. Because the payload is only encoded and readable by anyone with the token, never place passwords, secrets, or sensitive personal data in it. Store only non-sensitive claims and keep the token itself protected.