Decode JWT Payload
This JWT decoder separates a JSON Web Token into its three compact segments and reads the base64url-encoded JSON in the header and payload.
Run — free
It returns both sections as structured objects, making claims, identifiers, timestamps, issuers, audiences, and algorithm metadata easy to inspect or pass into another tool. The signature is deliberately not verified, so the decoded values describe what the token says rather than proving who created it. Use the result for debugging, development, documentation, and careful inspection, never as evidence that a token is authentic or authorized.
Understand what decoding does and does not prove
A JWT commonly contains a header, a payload, and a signature, joined by periods. The first two segments are base64url-encoded JSON, which means their contents are encoded for compact transport but are not encrypted or hidden. This capability splits the supplied token, decodes those two segments as UTF-8, parses their JSON, and returns the resulting header and payload objects. It does not use the third segment to authenticate anything. That distinction matters because anyone can construct a token-shaped string with arbitrary claims. Seeing a subject, role, issuer, audience, or expiration value in the decoded payload does not establish that a trusted system issued it. Use decoding when you need visibility into token structure, want to diagnose claim names or values, or need a readable representation for development. Use a proper JWT verification library with an explicitly trusted key, allowed algorithm, issuer, and audience whenever a security decision depends on the token.
Supply a compact JWT and interpret the response
Paste or send the complete compact JWT in the token field. A structurally valid token has exactly three segments separated by two periods, even though this decoder only reads the first two. The response contains a header object and a payload object. Typical header fields include typ, which often identifies the JWT media type, and alg, which names the claimed signing algorithm. Typical payload fields include sub for a subject, iss for an issuer, aud for an audience, exp for an expiration time, and application-specific claims. No claim is required by this decoder; it preserves the JSON values that are present. NumericDate claims such as exp, nbf, and iat remain numbers rather than being converted into dates, avoiding assumptions about how a caller wants to display or compare them. If the token has the wrong number of segments, malformed base64url, invalid UTF-8, invalid JSON, or a decoded section that is not an object, the request returns an invalid-input error instead of a partial result.
Use decoded claims safely in development workflows
Decoding is especially useful at the boundary between systems. An API developer can compare the claims produced by an identity provider with the names an application expects. A support engineer can inspect a redacted test token to discover whether an audience or scope is missing. A test suite can decode tokens created by a local fixture and assert that required custom claims were included before separately testing cryptographic verification. Keep the security boundary explicit in every workflow: decoded data is untrusted input. Do not grant access, select a tenant, accept an identity, or expose private data solely because a decoded claim requests it. Avoid pasting real bearer tokens into logs, tickets, chat, or shared documents, because a JWT may be a live credential even when its payload looks harmless. Prefer synthetic, expired, or locally generated examples for troubleshooting. When automation must process real tokens, send them only through an appropriately protected channel and follow decoding with verification performed against trusted configuration.
What you can do with it
Debug identity-provider claims
Inspect the header and payload shape to compare issued claim names, audiences, scopes, and identifiers with an application's configuration.
Check locally generated test tokens
Decode fixture tokens in tests or development scripts and confirm that expected custom claims are present before testing verification separately.
Explain token structure
Turn a compact JWT into readable JSON objects for technical documentation, training, or troubleshooting with synthetic and safely redacted examples.
FAQ
Does this verify the JWT signature?
No. It only decodes the header and payload. Treat every returned field as untrusted until a separate verifier validates the signature and required claims.
What does it cost?
The API price is $0.002 per request. The browser version can run the same deterministic decoding logic locally.
Why must the token have three segments?
Compact JWT serialization consists of a header, payload, and signature segment separated by periods. This capability rejects strings that do not have exactly that structure.
Are expiration timestamps converted to dates?
No. Values such as exp, nbf, and iat are returned exactly as represented in the payload, so callers can interpret them according to their own requirements.
Can I decode an unsigned JWT?
A compact token still needs three segments, so an unsecured token can have an empty third segment. The header and payload are decoded, but no security conclusion is made.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/web/jwt-decode \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.c2lnbmF0dXJl"}'const res = await fetch("https://api.kit.forhosting.com/web/jwt-decode", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.c2lnbmF0dXJl"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/jwt-decode",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.c2lnbmF0dXJl"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/jwt-decode", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.c2lnbmF0dXJl"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.c2lnbmF0dXJl"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/jwt-decode", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.c2lnbmF0dXJl"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.jwt_decode",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
timeout_sec | 30 |
max_crawl_pages | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |