jwt-decode
A lightweight TypeScript library for decoding JSON Web Token payloads and headers in the browser and Node.js.
Repository Health
Technical Analysis
jwt-decode is a zero-runtime-dependency library for decoding JSON Web Tokens (JWTs) in browser and Node.js environments. It exposes a single function, jwtDecode, that splits a JWT into its base64url-encoded segments and returns the decoded JSON payload (or header) as a plain object — it does not verify the token’s signature. Maintained by Auth0, it ships dual ESM and CommonJS builds plus a standalone browser script-tag entry point, and is one of the most widely depended-on packages in the JavaScript JWT ecosystem at roughly 18 million weekly downloads.
The library specifically handles the tricky parts of base64url decoding: non-standard padding lengths, UTF-8/unicode payload characters, and malformed input. It throws a typed InvalidTokenError with a descriptive message distinguishing between a non-string token, a missing segment, invalid base64, and invalid JSON, so callers can branch on failure without string-matching generic errors. Because it deliberately does not validate signatures, the README recommends pairing it with a server-side verification library (express-jwt, koa-jwt, or a framework’s built-in JWT bearer middleware) whenever a token’s authenticity must be trusted rather than just its claims read.
What You Get
- A single
jwtDecode()function that returns the parsed JWT payload or header as a typed object. - TypeScript types for
JwtHeaderandJwtPayload, extensible with your own custom claim shapes via generics. - A typed
InvalidTokenErrorclass with specific messages for missing parts, invalid base64, and invalid JSON. - Dual ESM/CommonJS build output plus a browser-ready ES module file for direct
<script type="module">use.
Common Use Cases
- Reading claims client-side - Decoding an access or ID token in a single-page app to read claims like
exporsubwithout a server round-trip. - Checking token expiry - Comparing the decoded
exp/iattimestamps in the browser to decide whether a session token needs refreshing before an API call. - Inspecting a JWT header for
kid- Passing{ header: true }to retrieve the header segment and select the correct signing key elsewhere in a verification flow. - Non-browser environments - Combined with an
atobpolyfill such ascore-js/stable/atob, decoding tokens in runtimes (e.g. older React Native) that lack a nativeatobglobal.
Under The Hood
Architecture
The library is intentionally a single module (lib/index.ts): one exported jwtDecode function, two private helpers (b64DecodeUnicode and base64UrlDecode) for the base64url-to-unicode transform, and an InvalidTokenError class. There is no internal layering, dependency injection, or I/O — jwtDecode is a pure synchronous string-to-object transform, so the entire “architecture” is a single, narrow surface. The build step compiles this one file twice, once each for tsconfig.cjs.json and tsconfig.esm.json, with a prebuild script stamping a package.json into the CJS output directory so Node resolves it as CommonJS. Given the package’s scale (tens of millions of weekly downloads), any change to the jwtDecode signature or error messages would ripple across an enormous number of consumers instantly, so the minimalism looks deliberate rather than accidental.
Tech Stack
Written in TypeScript with zero runtime dependencies (it relies only on the global atob), compiled with the native tsc compiler (no bundler like esbuild/tsup), and tested with Jest across both a node and a jsdom test environment to exercise browser and non-browser code paths. Linting uses ESLint 9’s flat config with typescript-eslint, formatting is enforced with Prettier and lint-staged/Husky pre-commit hooks, and package correctness is checked with publint. CI runs a Node 18/20 build matrix on GitHub Actions, with Snyk and Semgrep scanning for dependency and code-level security issues, and releases are automated via a dedicated npm-release workflow keyed off release branches.
Code Quality
The single test file exercises the default payload decode, header decoding via { header: true }, UTF-8 and binary payload edge cases, both single- and double-character base64 padding, and every InvalidTokenError branch (non-string input, missing token part, invalid base64, invalid JSON) — solid coverage for a small, focused surface area, though there’s no dedicated test asserting the compiled CJS/ESM build artifacts themselves. TypeScript strict typing is used throughout, errors are raised as a distinguishable typed class rather than generic Error throws, and every PR runs lint, format-check, and both test suites in CI before merge.
API Design
The public API is a single function with a sensible default (jwtDecode(token) decodes the payload; { header: true } opts into decoding the header instead), and overloaded TypeScript signatures give strong return-type inference based on that option without requiring a manual type assertion. There’s no setup, configuration object, or class instantiation required — install and call. The main friction points are the reliance on a global atob (requiring a polyfill in environments like older React Native) and the fact that “decode” deliberately does not mean “verify,” which the README calls out prominently since it is a common source of confusion for developers who assume decoding implies the token is trustworthy.
Used by 25 apps in this directory
Jitsi Meet
Collaboration · Team Chat · Video Conferencing
Open-source, end-to-end encrypted video conferencing you can self-host or embed into any web or mobile app.
LibrePhotos
File Storage
Self-hosted photo library with AI-powered face recognition, semantic search, and automatic event albums — no cloud required.
LiteLLM
AI Development · Developer Tools
Open source AI gateway and Python SDK that gives you one OpenAI-compatible interface to call 100+ LLM providers, with built-in routing, cost tracking, guardrails, and virtual keys.
Navidrome
File Storage · Music Audio
Run your own personal Spotify — stream your entire music collection from any device, anywhere, forever.
NocoDB
Databases · Low Code Platforms · No Code Platforms
Turn any SQL database into a collaborative no-code spreadsheet with automatic REST APIs and real-time views.
Novu
Developer Tools
Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.
OneUptime
Monitoring
The complete open-source observability platform that replaces PagerDuty, Datadog, Sentry, and StatusPage with a single self-hostable system.
OpenSign
Digital Signiture
Self-host a full-featured DocuSign alternative with unlimited e-signatures, multi-signer workflows, and cryptographic PDF signing.
Payload CMS
Blogging · CMS · Developer Tools
The open-source, Next.js-native headless CMS that lives inside your /app folder and gives you a full TypeScript backend instantly.