What Is a JWT? JSON Web Tokens Explained for Developers
By AZ Utils Editorial · · 12 min read
Open the network tab on almost any modern web app and you will find a long, three-part string riding along in the headers — something like eyJhbGci... with two dots in it. That is a JWT, or JSON Web Token, and it has become one of the most common ways for applications to prove who you are. This guide explains what a JWT is, what each of its three parts contains, how it is used, and the single most important thing developers get wrong about it.
It is written for developers and engineers building authentication, students learning how modern auth works, and technical beginners who keep seeing JWTs and want a clear mental model.
What Is a JWT?
A JWT (JSON Web Token) is an open standard — defined in RFC 7519 and usually pronounced "jot" — for representing claims securely between two parties. In plainer terms, a JWT is a compact, self-contained token that carries a small set of JSON data (the claims) and is cryptographically signed so the receiver can trust that the data has not been tampered with.
The word "claims" simply means statements about a subject. A typical authentication JWT makes claims like "this token represents user 123," "it was issued by example.com," and "it expires at 3:45pm." Because the token is signed, a server that receives it can verify those claims are genuine without having to look anything up in a database — the trust comes from the signature, not from server-side state. That self-contained, verify-without-a-lookup property is the whole reason JWTs exist and why they power so much of modern, scalable authentication.
A JWT is also compact and URL-safe: it is encoded as text that fits comfortably in an HTTP header, a URL or a cookie, so it travels easily between clients and servers and across services.
In short: A JWT is a compact, URL-safe, digitally signed token that carries JSON claims between parties. Its signature lets a receiver verify the claims are authentic and untampered, without needing to store session state.
The Three Parts of a JWT
A JWT is three Base64url-encoded sections joined by dots: header.payload.signature. Each dot separates a part, which is why every JWT has exactly two dots. Here is a (wrapped) example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjMiLCJuYW1lIjoiQWRhIiwiaWF0IjoxNzAwMDAwMDAwfQ
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Let's decode each part.
1. The header
The header is a small JSON object describing how the token is signed. It almost always contains two fields: the signing algorithm (alg) and the token type (typ):
{
"alg": "HS256",
"typ": "JWT"
}
The alg value — such as HS256 (HMAC with SHA-256) or RS256 (RSA signature) — tells the receiver which algorithm to use when verifying the signature. As we will see, blindly trusting this field is a classic source of vulnerabilities.
2. The payload
The payload is a JSON object holding the claims — the actual data the token carries:
{
"sub": "123",
"name": "Ada",
"iat": 1700000000,
"exp": 1700003600
}
Here sub (subject) identifies the user, iat is the issued-at time, and exp is the expiry. These short, standardised names are called registered claims; you can also add your own. We cover the full set in Common JWT Claims.
3. The signature
The signature is what makes a JWT trustworthy. It is created by taking the encoded header and payload, joining them with a dot, and signing that string with a secret (for HMAC) or a private key (for RSA/ECDSA):
HMACSHA256(
base64url(header) + "." + base64url(payload),
secret
)
When a server receives the token, it recomputes the signature over the header and payload using its key and checks that it matches the signature in the token. If even one character of the header or payload was changed, the signatures will not match and the token is rejected. This is how a JWT guarantees integrity — proof that the contents have not been altered.
A Decoded Example
Decoding the example above gives a header that says it is an HS256-signed JWT, and a payload claiming the subject is user 123, named Ada, issued at a particular time. The signature is verified against the server's secret. You can decode any token yourself, safely and instantly, with our JWT Decoder — it runs entirely in your browser, so the token never leaves your device, which matters because tokens are sensitive.
The Crucial Point: Signed, Not Encrypted
Here is the single most important thing to understand about a standard JWT: it is signed, not encrypted. The header and payload are only Base64url-encoded, which is reversible by anyone. That means anyone holding the token can read its payload — the claims are not secret.
The signature provides integrity (you can tell if the data was changed) and authenticity (you can tell it came from someone with the key), but it provides no confidentiality (it does not hide the contents). The practical consequence is a rule you must never break: never put secrets in a JWT payload — no passwords, no private keys, no sensitive personal data. If the contents genuinely must be hidden, you need an encrypted token (JWE) or you keep that data on the server. Treating the encoding as if it were encryption is the most common and most dangerous JWT misconception.
Featured-snippet target: A JWT has three parts — header, payload and signature — separated by dots. The header and payload are Base64url-encoded JSON (readable by anyone), and the signature lets the receiver verify the token has not been tampered with. A standard JWT is signed, not encrypted.
Why JWTs Became Popular
JWTs did not become ubiquitous by accident; they solved a real problem that grew sharper as applications spread across many servers. In the classic model, a logged-in user's state lived on one server, which meant every request had to reach that server or a shared session store. As teams scaled horizontally and split monoliths into services, that shared state became a bottleneck and a coupling point. A self-contained, signed token sidesteps the whole issue: any service holding the verification key can authenticate a request on its own, with no network call to a session database. That single property — verify locally, trust globally — is what made JWTs the default for APIs, single-page applications and microservice architectures.
The format also fit the grain of the modern web. It is built on JSON, which every language and browser already parses; it is compact enough to sit in a header; and it is URL-safe thanks to Base64url. It slotted naturally into standards like OAuth 2.0 and OpenID Connect, which use JWTs to represent access grants and authenticated identities. The result is a token format that is both technically convenient and widely interoperable — you can mint a token in one stack and verify it in a completely different one without friction.
The JOSE Family: How JWT Fits In
A JWT is one member of a broader set of standards known as JOSE (JavaScript Object Signing and Encryption). Understanding the family clears up a lot of confusion:
- JWS (JSON Web Signature) defines how data is signed. A standard, signed JWT is technically a JWS — which is exactly why its contents are readable but tamper-evident.
- JWE (JSON Web Encryption) defines how data is encrypted. If you genuinely need the payload to be secret, a JWE-based token is the tool, not a plain JWT.
- JWK (JSON Web Key) is a JSON format for representing cryptographic keys, often served from a JWKS endpoint so verifiers can fetch and rotate public keys.
- JWA (JSON Web Algorithms) defines the algorithm identifiers, like HS256 and RS256, that appear in the header.
When people say "JWT," they almost always mean a signed JWS-based token carrying claims. Knowing that encryption (JWE) and key formats (JWK) are separate, sibling standards helps you reach for the right one when the requirement changes.
How JWTs Are Used
By far the most common use of JWTs is stateless authentication. After you log in, the server creates a JWT describing your identity, signs it, and sends it to your browser or app. From then on, your client includes that token with each request, and the server verifies the signature to know who you are — without storing a session record. Because nothing needs to be looked up server-side, this scales beautifully across many servers and microservices.
JWTs are also used for authorization (carrying roles or permissions as claims), information exchange between services that trust a shared key, and short-lived access grants like password-reset or email-verification links. The full login-to-access flow is explained in JWT Authentication Explained, and how this approach compares to traditional server sessions is covered in JWT vs Session Authentication.
Working with JWTs in Code
You should almost never parse or verify JWTs by hand — use a well-maintained library, because the security depends on getting verification exactly right. Decoding (reading) and verifying (trusting) are different operations, and you must always verify before trusting a token.
Node.js
import jwt from "jsonwebtoken";
// Create (sign) a token
const token = jwt.sign(
{ sub: "123", name: "Ada" },
process.env.JWT_SECRET,
{ expiresIn: "1h" }
);
// Verify a token — throws if invalid or expired
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
console.log(payload.sub); // "123"
} catch (err) {
// invalid signature, expired, or malformed
}
Python
import jwt # PyJWT
token = jwt.encode({"sub": "123", "name": "Ada"}, SECRET, algorithm="HS256")
try:
payload = jwt.decode(token, SECRET, algorithms=["HS256"])
print(payload["sub"]) # "123"
except jwt.InvalidTokenError:
# invalid or expired
...
Notice that the verify step always specifies the expected algorithm. That detail matters enormously for security, as we explain in JWT Security Best Practices.
Try Our Free JWT Decoder
The quickest way to inspect a token is our JWT Decoder. Paste a JWT and instantly see its decoded header and payload, including human-readable timestamps for claims like iat and exp.
- ✅ Decodes header and payload instantly
- ✅ Runs entirely in your browser — tokens never leave your device
- ✅ Free, with no sign-up
Reading a JWT at a Glance
With the structure in mind, you can interpret most tokens just by looking at them. The two dots immediately tell you it is a JWT and divide it into header, payload and signature. A header beginning eyJhbGci is simply the Base64url encoding of text that starts with {"alg":, so almost every JWT header looks similar at the start. The middle section is the longest because it carries the claims, and the final section is the signature, which looks like random characters because it is raw signed bytes rendered in Base64url. If you see - or _ characters anywhere, you are looking at the URL-safe alphabet, which is normal for tokens. None of this requires decoding by hand — but recognising the shape helps you spot, for instance, a malformed token that is missing a section, or a suspiciously large payload that suggests someone has stuffed too much data into the claims. When you do want the details, a decoder turns the opaque string into readable JSON in an instant.
Common Mistakes
- Thinking the payload is private. It is only Base64url-encoded and readable by anyone. Never store secrets in it.
- Decoding without verifying. Reading a token's claims is not the same as trusting them; always verify the signature first.
- Trusting the
algheader blindly. Accepting whatever algorithm the token claims — includingnone— opens serious vulnerabilities. Always pin the expected algorithm. - Ignoring expiry. Failing to check
explets old tokens live forever. - Making tokens long-lived with no revocation plan. A stolen long-lived JWT is valid until it expires, so keep lifetimes short.
- Storing tokens carelessly. Putting a JWT in a place exposed to cross-site scripting risks theft.
Best Practices
- Always verify the signature with a trusted library and a pinned algorithm before using any claim.
- Keep payloads minimal and non-secret. Store only what you need to identify and authorize the user.
- Use short expiry times and a refresh-token strategy for longer sessions.
- Use strong secrets or proper key pairs, and rotate them.
- Send tokens over HTTPS only, and store them carefully (httpOnly cookies are often safer than localStorage).
- Have a revocation plan — short lifetimes, a denylist, or rotating refresh tokens.
When to Use (and Not Use) JWTs
JWTs shine when you need stateless, cross-service authentication — APIs, microservices, single-page apps and mobile clients all benefit from a self-contained token that any service can verify with a shared key. They are also a natural fit for short-lived, single-purpose tokens such as email-verification or password-reset links, where a signed, expiring claim is exactly what you want.
They are a weaker fit when you need easy, immediate revocation or you are building a traditional, single-server, server-rendered application. In those cases a classic server session — where the server holds the state and can delete it instantly — is often simpler and safer. The trade-offs between the two approaches are worth understanding before you choose; see JWT vs Session Authentication for the full comparison.
Frequently Asked Questions
What does JWT stand for?
JWT stands for JSON Web Token. It is an open standard (RFC 7519) for a compact, URL-safe, digitally signed token that carries JSON claims between two parties.
What are the three parts of a JWT?
A JWT has a header, a payload and a signature, separated by dots. The header and payload are Base64url-encoded JSON, and the signature lets the receiver verify the token has not been tampered with.
Is a JWT encrypted?
No. A standard JWT is signed, not encrypted. The header and payload are only Base64url-encoded, so anyone holding the token can read them. Never put secrets in a JWT payload.
Can a JWT be tampered with?
Not without detection. If anyone changes the header or payload, the signature no longer matches when the server verifies it, so the token is rejected — provided the server actually verifies the signature.
Where are JWTs stored?
On the client, typically in an httpOnly cookie or in browser storage. httpOnly cookies are generally safer because they are not accessible to JavaScript, reducing the risk of theft via cross-site scripting.
Are JWTs secure?
They can be, when implemented correctly: verify the signature with a pinned algorithm, validate claims like expiry, keep payloads non-secret, use short lifetimes and transmit only over HTTPS. Misusing them — trusting unverified tokens or treating the payload as private — is where security fails.
How do I read what is inside a JWT?
Decode the Base64url header and payload. The easiest way is to paste the token into a JWT decoder, which shows the claims and human-readable timestamps without sending the token anywhere.
Summary
A JWT is a compact, signed, self-contained token that carries JSON claims between parties. Its three dot-separated parts — header, payload and signature — let a receiver verify, using only a key, that the claims are authentic and untampered, which is what makes stateless authentication possible. The defining caveat is that a standard JWT is signed, not encrypted: the payload is readable by anyone, so it must never hold secrets. Get the fundamentals right — always verify with a pinned algorithm, keep payloads minimal, use short lifetimes and transmit over HTTPS — and the JWT becomes a powerful, scalable building block for modern authentication. To explore one safely, decode it with the free tool below.
👉 Decode and inspect a JWT with our free tool →
Related Resources
- JWT Decoder — inspect a token in your browser
- JWT Authentication Explained — the login-to-access flow
- Common JWT Claims — what each claim means
- JWT Security Best Practices — use JWTs safely
- JWT vs Session Authentication — the trade-offs