JWT Decoder Template
- Next.js
- TypeScript
Paste a JSON Web Token and read its header, claims and expiry in plain words.
A Next.js app that decodes JSON Web Tokens. Paste a token and see each part colour-coded, every claim named in plain words, timestamps turned into dates, and whether the token has expired. Use it to debug an auth flow, or lift the route to inspect tokens inside your own tools.

What it does
- Claims in plain words
- Names each registered claim, such as issuer, subject, audience and expiry, next to its raw key.
- Expiry at a glance
- Shows whether the token is expired or not valid yet, and how long it has left, with timestamps as dates.
- Colour-coded token
- Splits the pasted token into header, payload and signature so you can see which part is which.
- Checks before it spends
- The route checks the token has three parts before calling the API, and caches answers under a hash of the token.
- Keeps your key private
- The browser only talks to your own API route, which holds the key and limits each visitor to 10 decodes a minute.
How it works
The route: check the token's shape, answer from the cache, then call JWT Decoder.
export async function POST(request: Request) {
const body = await request.json().catch(() => null);
const token = String(body?.token ?? '').trim();
if (!token) return fail('Paste a JWT to decode');
if (token.length > 8000) return fail('That token is too long');
if (!JWT_SHAPE.test(token)) return fail('A JWT has three parts separated by dots: header.payload.signature');
const key = `jwt:${createHash('sha256').update(token).digest('hex')}`;
const hit = fromCache(key, TTL_MS);
if (hit) return Response.json(hit);
const blocked = guard(request);
if (blocked) return blocked;
return respond(async () => {
const data = await callApi('jwtdecoder', { json: { token } });
toCache(key, data);
return data;
});
}Deploy it
- Get a free API key
The free plan includes 200 credits a month, no card needed. Create your key.
- Deploy it
Click Deploy to Vercel. Vercel copies the repo to your GitHub account and asks for
APIVERVE_API_KEY: paste your key there. - Open your app
Vercel builds it and gives you a live URL, usually in about a minute. Every push to the repo redeploys it.
Try the JWT Decoder API — the call this template makes
No key required to try it. Get a key to use it in your app.
{
"status": "ok",
"error": null,
"data": {
"header": {
"alg": "RS256",
"typ": "JWT",
"kid": "sample-key-1"
},
"payload": {
"sub": "1234567890",
"name": "John Doe",
"iss": "https://auth.example.com",
"aud": "api.example.com",
"iat": 1767225600,
"exp": 2082758400
},
"signature": "hP0O9ELZGk-KN3upyYqdOnPY2Ig7FAzfUY_xytzOCBIhn0_TWdzl2dbLPlj0rkCDsRIQX0I5t9Xv551VI1W9dmvRGtVztyeD3IKHnIn24baOUtjU7Eb6FHL_iWMu5PqMeQJPFytuYbYhzjjCNfFPgAciGgn1Celr8H7_q51x5naMb-nbTvBc5SIX9MBnegGzabExBYQ-OsdKOoYmK0uymNIgC3834jlPuhuJHkPsxX7ncKoSQ4wheiLaZDwFANlT1NrD2XgKyyh-LIIg9CRwqB_WDktZ_R6UusNkLRhKJ20ff29ttkyRhJZzEqRRK60xYn7iPyg4YQni1J_w-oAa_w",
"isExpired": false,
"expiresAt": "2036-01-01T00:00:00.000Z",
"issuedAt": "2026-01-01T00:00:00.000Z",
"tokenAge": "309 days",
"algorithm": "RS256",
"expiresIn": 288757380,
"notYetValid": false,
"securityAnalysis": {
"isUnsecured": false,
"hasExpiration": true,
"isLongLived": true,
"issues": [
"Token lifetime exceeds 24 hours"
]
},
"warning": "Signature verified with the supplied public key.",
"signatureVerification": {
"verified": true,
"algorithm": "RS256",
"keyType": "RSA",
"reason": null,
"claimsValid": true,
"claimsReason": null
}
}
}