JWT Decoding: How to Read Tokens Without a Library

1 6 114
calendar_todayschedule2 min read

A JSON Web Token (JWT) has three dot-separated parts: header, payload, and signature. The first two are just Base64url-encoded JSON. You can decode them in a single line — no library needed.

The one-liner

JavaScript:

`<code>javascript</p> <p>const payload = JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));</p> </code>

Python:
<code>python <p>import base64, json</p> <p>part = token.split('.')[1] + '===' # pad</p> <p>payload = json.loads(base64.urlsafe_b64decode(part[:len(part)//4*4]))</p> </code>

That gives you the decoded payload as an object — user ID, expiry time, roles, whatever the token contains.

What is in the payload

A typical payload:

<code>json <p>{</p> <p>"sub": "user_12345",</p> <p>"email": "*Emails are not allowed*",</p> <p>"iat": 1717200000,</p> <p>"exp": 1717286400,</p> <p>"roles": ["user", "admin"]</p> <p>}</p> </code>

The standard claims you will see:

| Claim | Meaning |

|---|---|

| sub | Subject — usually the user ID |

| iss | Issuer — who created the token |

| aud | Audience — who it is intended for |

| exp | Expiry — Unix timestamp (seconds) |

| iat | Issued at — Unix timestamp |

| nbf | Not before — earliest valid time |

exp and iat are Unix timestamps. Use a Unix timestamp converter to read them as dates.

Decoding ≠ verifying

Decoding is not verification. Anyone can decode a JWT — the payload is encoded, not encrypted. If your server needs to trust the claims (check permissions, validate session), it must verify the signature using the correct key.

<code>javascript <p>// Node.js — verify the signature before trusting claims</p> <p>const decoded = jwt.verify(token, process.env.JWT_SECRET);</p> </code>

Never skip verification in production. A decoded-but-unverified token can be forged.

Debugging common JWT errors

"Token expired" — decode the payload, check exp. Compare to the current Unix timestamp. If it is less than Date.now() / 1000, the token is expired. Also check server clock drift — a few seconds of NTP drift can cause spurious expiry errors.

"Invalid signature" — the token was signed with a different key, or the payload was modified. Check your key management: are you using the same secret for signing and verification? For RS256, confirm you are using the public key at the correct JWKS endpoint.

"Invalid audience" — check aud`. It must match what your application expects. Tokens issued for one service are often rejected by another.

Quick inspection

For development debugging — reading token contents, checking expiry, verifying claim structure — the JWT Decoder on SnappyTools shows all claims with timestamps converted to readable dates. Runs in your browser; the token is never sent anywhere.


Paste a JWT at snappytools.app/jwt-decoder/ to inspect header, payload, and claim types instantly.

Originally published at https://snappytools.app/jwt-decoder/</a></em></p>

🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

How I Built a React Portfolio in 7 Days That Landed ₹1.2L in Freelance Work

Dharanidharan - Feb 9

What Is SARIF and How Does It Help Security Tools Work Together?

Ganesh Kumar - Jul 4

TypeScript Complexity Has Finally Reached the Point of Total Absurdity

Karol Modelskiverified - Apr 23

Sovereign Intelligence: The Complete 25,000 Word Blueprint (Download)

Pocket Portfolio - Apr 1
chevron_left
2.4k Points121 Badges
101Posts
0Comments
SnappyTools builds free, fast, browser-based tools for developers, writers, and designers. No signup... Show more

Related Jobs

View all jobs →

Commenters (This Week)

1 comment
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!