JWT Decoder & Claims Inspector

Paste any JWT to inspect its header, payload, and expiry. Nothing leaves your browser.

ZERO UPLOAD · ALL LOCAL

What to look for

  • seconds (NumericDate), never milliseconds
  • 30-300 seconds

A decoded exp that lands in 1970 or thousands of years out is the classic seconds-vs-milliseconds mix-up, not a real expiry problem.

What this page covers

  • alg check first; an RS256 header verified with an HMAC secret is an algorithm mismatch, not a secret problem
  • kid must appear in the provider's current JWKS; a missing kid points to key rotation or the wrong issuer
  • iss and aud confirm the token belongs to your issuer and service before assuming the key material is wrong

What to look for

  • 2048-bit (4096-bit for extra margin)
  • 256-bit EC key ~= 3072-bit RSA

Decode the token above to read alg first; your verification code should enforce the expected algorithm rather than trusting the header.

What to look for

  • 5-60 minutes
  • hours to days

Decode your access token above to confirm its exp before assuming a refresh failure is the cause of a 401.

What to look for

  • 2.13.0
  • 3.9+

The cryptography extra is only needed for RS256/ES256 verification, not for HMAC algorithms.

What this page covers

  • jose decodeJwt() browser/ESM-friendly, no key required for reading claims
  • jsonwebtoken jwt.decode() Node.js only; pass { complete: true } to also read the header

What to look for

  • golang-jwt/jwt v5
  • CVE-2020-26160

Use jwt.NewParser().ParseUnverified() to decode without verifying, and a typed claims struct to read provider-specific fields.

What this page covers

  • Jwts.parser().parseClaimsJwt() reads claims without verifying, using JJWT's builder API
  • claims.get(name, Type.class) reads a custom claim with an explicit type instead of a raw Map cast

What this page covers

  • JwtSecurityTokenHandler.ReadJwtToken() reads claims without verifying, from System.IdentityModel.Tokens.Jwt
  • jwt.Claims.FirstOrDefault(c => c.Type == "...") matches provider-specific claims by string, since they have no ClaimTypes constant

What this page covers

  • Header encodes the signing algorithm (alg) and token type (typ)
  • Payload encodes the claims: identity, expiry, roles, and any custom fields
  • Signature a cryptographic hash of the header and payload; detects tampering, does not hide the content

What this page covers

  • iss, sub, aud issuer, subject, and audience: the seven RFC 7519 registered claims include these three identity/routing fields
  • exp, nbf, iat the three NumericDate time claims that define a token's validity window
  • jti a unique token ID, used for replay-attack prevention via a short-lived seen-cache

What to look for

  • ~90 days
  • n (modulus) + e (exponent)
  • crv (curve) + x, y (point)

Decode the token above to read its kid, then match it to the correct entry in the provider's JWKS.

What this page covers

  • Auth0 https://<tenant>.auth0.com/
  • Google https://accounts.google.com
  • Okta https://<org>.okta.com/oauth2/default
  • Azure AD https://login.microsoftonline.com/<tenantId>/v2.0
  • Supabase https://<ref>.supabase.co/auth/v1

What this page covers

  • Auth0 google-oauth2|108512345 (social) or auth0|64a1b2c3 (database connection)
  • Google a stable numeric string, e.g. 108512345678901234567
  • AWS Cognito / Keycloak a UUID, e.g. a1b2c3d4-e5f6-7890-abcd-ef1234567890
  • Clerk a prefixed string, e.g. user_2abc123def

What to look for

  • NumericDate: seconds since Unix epoch
  • 5-60 minutes
  • 30-60 seconds

A decoded exp landing in 1970 means the issuer sent milliseconds where seconds were expected.

What this page covers

  • Auth0 API audience URL (access token) or client_id (ID token)
  • Azure AD the application (client) ID GUID
  • AWS Cognito omits aud from access tokens entirely; substitutes client_id instead

What this page covers

  • Authorization: Bearer <token> the exact RFC 6750 header format; parsers split on the first space
  • Access token storage in memory only, never localStorage or sessionStorage
  • Refresh token storage an HttpOnly, Secure, SameSite cookie scoped to the refresh endpoint

Output (Decoded token)

HEADER
          
PAYLOAD
          
EXPIRY
  1. Copy your JWT token — it looks like three Base64 sections separated by dots (eyJ…)
  2. Paste the token into the input field — decoding happens automatically on paste.
  3. Read the Header panel: it shows the signing algorithm (alg) and token type (typ).
  4. Read the Payload panel: it shows all claims — user ID, roles, issued-at (iat), and expiry (exp).
  5. Check the expiry status indicator — it shows whether the token is currently valid or expired, with a human-readable time delta.
  6. Note: the tool decodes only — it does not verify the signature. Never trust decoded claims in a security context without server-side verification.

What is a JWT?

A JSON Web Token (JWT) is a compact, URL-safe format for representing claims between two parties.1 It consists of three Base64Url-encoded sections separated by dots: a header naming the algorithm and token type, a payload carrying the claims, which typically include a user ID, a set of roles, an expiry, and any custom fields, and a signature binding the first two parts together so the receiver can verify the token was created by a trusted party.2 The format is defined by the IETF in RFC 7519 and is widely used for both authentication tokens and information exchange.

A widely published example token makes the three parts concrete before you paste your own. Pasting eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c into the inspector decodes to a header of {"alg":"HS256","typ":"JWT"} and a payload of {"sub":"1234567890","name":"John Doe","iat":1516239022}, while the third section stays as an opaque signature the tool never attempts to check. This is a well-known public sample token, not a real credential, so it is safe to paste anywhere for testing the decoder.

Structure of a JWT

The header is a JSON object naming the algorithm used to produce the signature and identifying the token as a JWT. The payload is a second JSON object whose members, called claims, carry the information the token exists to convey: for example, who the token is for, what it grants, and when it stops being valid. The signature is a cryptographic hash or digital signature computed over the encoded header and encoded payload, optionally also covering a shared secret or a private key known only to the issuer, which is what makes the token tamper-evident but readable by anyone who holds it.

Where JWTs are used

JWTs are a widely used format for stateless authentication in web APIs.3 When a user logs in, the server issues a JWT. The client sends it with every request (typically in the Authorization: Bearer <token> header), and the server verifies the signature rather than looking up a session in a database.4 This bearer-token pattern, defined by RFC 6750, is what lets a single token travel across microservices while centralizing authentication at the issuer.3

Because the token itself carries the claims, the server does not need to keep session state in memory or in a database, which makes JWTs attractive for distributed systems and single sign-on. In those architectures many services must independently accept the same authorization decision without relying on a central session store, and the self-contained nature of the token is what makes that independence possible.

Why decode offline?

Most popular JWT inspection tools are server-backed websites. When you paste a token, the full token, including the signature, is transmitted to a third-party server. For tokens that grant access to production systems, this is a critical security violation: any party that captures your token can impersonate you until it expires.4

This tool performs all decoding in your browser using the built-in atob() function and JavaScript's JSON.parse. No token data, no claims, and no metadata are ever transmitted over the network: the Base64Url decoding, JSON parsing, and expiry comparison all happen inside your current browser tab without making any HTTP request to a decoding service. The tool works fully offline once the page has loaded, and reloading it does not re-send any token you previously decoded.

TIP You can disconnect from the internet after loading this page and it will continue to decode tokens exactly the same way. Your tokens never leave the tab, with no network request and no analytics call, so decoding traffic never appears on the network your machine is connected to. This means you can inspect production credentials in a sensitive environment without ever exposing those tokens to a third-party service.

Understanding the exp claim

The exp claim (expiration time) is a NumericDate value, meaning a Unix-style timestamp counting the number of seconds since January 1, 1970 UTC, and the token must not be accepted once the current time is at or after that moment.5 The tool compares exp against the current time shown on your device and reports whether the token has expired, along with a human-readable delta that tells you how long ago it expired or how long it has left, which makes the numeric claim immediately legible for debugging.

JWT decoder showing the header with alg HS256, the payload with sub, name and iat claims, and an expiry note
The decoded header shows alg HS256 and typ JWT. The payload carries sub 1234567890, name John Doe and iat 1516239022, and the expiry row reports no exp claim, so this token never expires.

Not every JWT carries an exp claim. Long-lived service-to-service tokens and static API keys are sometimes issued without one so that they remain valid until explicitly revoked through some other mechanism such as a token blocklist.6 When the claim is absent, the inspector displays a clear "No exp claim; token does not expire" message rather than guessing the validity window, so you can tell at a glance whether the token you are inspecting is meant to time out.

What happens after exp: the refresh cycle

Why would anyone issue a token that expires? Short lifetimes limit how long a stolen bearer token stays dangerous, so issuers pair the access token with a second, longer-lived refresh credential whose only job is obtaining new access tokens when the current one expires.7 A client that suddenly starts collecting 401s after a period of working usually hit an access token whose exp passed between refreshes: the failure is the design doing its job, not a mystery. The interesting question is why the refresh stopped happening, and the answer lives in the client, not the token.

Decode the failing access token and read iat together with exp. A stale iat sitting next to an expired exp means the token was issued long before its final rejection, so the refresh step stopped happening some time ago; a fresh iat next to a near-term exp means the loop is working and the expiry is ordinary. The refresh credential itself is a different token with a different lifetime and often a different format, so the two are decoded and reasoned about separately, never compared field for field. Paste each into the inspector on its own and read its own claims.

Why the signature is not verified

Verifying a JWT signature requires knowledge of the key the issuer used to sign the token: for symmetric HMAC algorithms like HS256 that means the shared secret itself, and for asymmetric algorithms like RS256 and ES256 that means the issuer's public key.2 This tool is an inspector rather than a validator. It decodes exactly what is present in the token but it cannot confirm whether the issuing server still considers the token authentic and unrevoked.8

The header is a claim, not a fact

The alg header states what the issuer claims to have used, and it travels inside the signed message, so a verifier must decide its own expected algorithm rather than following the header's suggestion. A real class of attacks works exactly that way: switching the header to none, or to a different family than the verifier assumed, lets a permissive library validate with the attacker's chosen math instead of the issuer's.9 The defense is to pin the expected algorithm on the verifying side and reject anything else. A header you can read is not a header you can trust.

Reading the header here is safe by design. The inspector displays alg and typ as decoded data and never acts on either, which is exactly how these fields should be read by a debugging tool. For troubleshooting, the displayed algorithm is the starting point of the HS-versus-RS choice your system made, and of any mismatch between what your provider issues and what your verifier expects; a token claiming HS256 in a system configured for RS256 keys fails in ways this panel makes obvious before you touch a server log. Nothing on this page validates a token; every field here just informs you.

The kid header and the key set

Asymmetrically signed tokens commonly carry a kid (key ID) in the header, naming which of the issuer's keys produced the signature. Issuers rotate keys and publish several at once, so the header's kid is the piece that tells a verifier which key to try, rather than assuming one key forever.10 When a token that used to verify suddenly stops after the issuer rotated keys, a key-set mismatch is the first thing to check, and the header panel above shows the token's own kid the moment you paste it. Match that value against the issuer's published set and you know which side of the rotation the token predates.

The key set is the other half of the mechanism. A JWKS is a JSON document, published by the issuer, that lists the current public keys; each entry can carry its own kid, so a verifier fetching the document can find exactly the key this token's header names.10 That is what the earlier verification walkthrough means by fetching the issuer's public keys: one document, several keys, matched by identifier. Decoding the header here shows which kid a token claims, which is the first value to match against that set when signature verification fails.

Performing real signature validation

To actually verify a token's signature you need to fetch the issuer's public keys, typically from a JSON Web Key Set (JWKS) endpoint, and use a well-maintained library running on the server side where the secret or private validation inputs can stay protected. The jose library is one widely used option that supports HMAC, RSA, and elliptic curve algorithms and lets you validate the signature, the expiry, the audience, and the issuer in a single call.8

Never trust a JWT's claims in a security-sensitive context without first verifying the signature server-side, because decoding a token only reveals what was placed inside it, not whether that content was produced by a party you actually trust or whether the key it was signed with has since been rotated. Treat the inspector as a debugging aid, and treat server-side signature verification and claims validation as the only authoritative gate for letting a request through.

Standard registered claims beyond exp

The JWT specification (RFC 7519) defines seven standard registered claim names, none of which are required, but several of which are widely useful for interoperable token validation.6 The inspector shows each claim present in the payload, so you can immediately see which standard claims your issuer includes and which it omits.

Claims that identify the token

The iss (issuer) claim identifies the principal that issued the token, typically a URL matching the authorisation server's base URL, and provides the hint your server uses to find the public key it needs to verify the signature. The sub (subject) claim identifies the principal the token is about, commonly a user ID or an application identifier in your system, and is almost always present because without it a bearer token has no clear owner. The aud (audience) claim identifies which services should accept the token; a token issued for your API should not be accepted by a different service, and correctly validating the audience claim prevents cross-service token replay attacks.1

Claims about timing and uniqueness

The nbf (not before) claim sets the earliest time the token is valid, useful for tokens issued slightly ahead of their intended use window. The iat (issued at) claim gives the exact issuance timestamp, letting you calculate how old a token is relative to its expiry and decide when a token has outlived its useful life. The jti (JWT ID) claim provides a unique identifier for the token, enabling server-side token revocation: if your backend stores issued JTIs in a blocklist, it can reject specific tokens before they expire without invalidating all sessions. Despite their usefulness, all seven registered claims are optional, and many issuers omit the ones they do not need.

Provider-specific claim shapes

Beyond the standard seven, identity providers layer their own conventions on top. Custom claims arrive namespaced under collision-resistant keys so they never collide with registered names;5 role and permission arrays appear in provider-specific shapes; and separate token types carry access versus identity, each with a different claim layout. The standard names keep their exact meaning no matter who issued the token, while everything an individual provider adds lands in its own namespaced keys. That division is what lets one inspector read tokens from any issuer: the shared core is predictable, and the rest is decoration you can look up in the provider's own documentation.

The inspector earns its keep on provider differences. Paste a token from a working session and one from the broken session of the same flow, and compare the claim sets side by side: provider-specific problems surface as claim-level diffs, a missing namespace, a swapped token type, a role array that changed shape. That comparison is the fastest route from a provider's documentation to what it actually put in your token, because the docs describe the layout while the decoded payload is the layout. Two pastes and a glance usually beat an hour of log spelunking.

Debugging authentication flows with the inspector

Authentication bugs often manifest as token-related errors that look identical from the outside but have different root causes. A 401 response could mean the token is expired, the signing algorithm does not match the server's expectation, the audience claim is wrong for this endpoint, or the subject claim contains an ID that no longer exists in your database. Pasting the token into the inspector immediately shows the algorithm, all claims, and whether the token has expired relative to your local clock, eliminating several possibilities at once without writing any debug code. Furthermore, comparing two tokens issued by the same flow, one from a working session and one from a broken session, often reveals the exact claim difference causing the failure.

Reading a Token with the JWT Inspector

Most authentication bugs come down to one question: what did the issuer actually put in the token? You can answer it without the signing key, because the header and payload are only Base64Url-encoded. The guide below covers what each decoded section shows, how the header differs from the payload, when a browser inspector is the right tool and what it cannot tell you about whether a token is valid.

During debugging, a JWT inspector Base64Url-decodes the three dot-separated sections of a signed JWT and renders them as human-readable JSON.12 The header section reveals the signing algorithm and key ID; the payload reveals the claims the issuer included, such as user ID, expiry, roles, and custom data. Paste any JWT into the decoder above to inspect it instantly. The tool requires no server connection and transmits no token data, making it safe to use with production tokens you cannot expose to third-party websites.

Inspecting rather than verifying is the right move during debugging. You do not need to know the signing key to read the contents of a JWT: the payload is only encoded, not encrypted. Seeing the raw claims confirms whether the expected fields are present, whether the exp timestamp has passed, and whether the algorithm matches what your server expects.3 Because offline inspection reveals no secret, you can safely inspect tokens from staging, QA, and production without risk of credential exposure.

What the inspector shows

Pasting a JWT into an inspector reveals three distinct panels. The header panel shows the signing algorithm (alg) and token type (typ), with an optional kid claim that identifies which key to use for verification. The payload panel renders all claims in formatted JSON: standard fields like iss, sub, exp, and iat, alongside provider-specific claims like realm_access (Keycloak) or cognito:groups (AWS Cognito). Furthermore, the inspector highlights exp in human-readable format: 'Expires in 14 minutes' is more useful than a raw Unix timestamp during an active debugging session, because the relative time remaining tells you immediately whether expiry is the cause of a 401 error.

Header vs payload

The JWT header specifies how the token was signed, not who signed it. alg tells you the algorithm: HS256 for symmetric HMAC, RS256 for RSA, ES256 for ECDSA.3 kid identifies the specific key among potentially many in the issuer's JWKS, enabling your verifier to select the correct public key when the provider rotates signing keys. Conversely, the payload contains the actual claims: sub identifies the subject (user or service), iss names the issuer, and exp marks the expiry boundary that determines when the token must be rejected.

Both header and payload are Base64Url-encoded structures that are readable by anyone with access to the raw token string, which is why an inspector can show you every claim without needing the issuer's private key or JWKS endpoint. Only the signature section requires cryptographic verification, because the signature is a mathematical proof that binds the header and payload to the issuer's private key and detect any single-character alteration.

Reading alg without trusting it

The alg value tells your verifier which algorithm to expect, but it should not be the only control. Your server should reject unexpected algorithms and compare kid against the issuer's current key set. An inspector makes the header visible; your verification code decides whether the token is valid. Hard-coding the expected algorithm list in your verification middleware, rather than reading alg from the incoming token header, prevents algorithm confusion attacks where an attacker swaps RS256 for HS256 to exploit a known server-side vulnerability.

When to use a browser inspector

Use a browser-based JWT inspector whenever you need to examine a token without transmitting it to a server. Debugging an expired token, confirming a missing claim, or verifying that a custom claim was injected correctly all require only the decoded payload: no signature check needed. Yet for security-sensitive operations, never rely solely on inspection: always verify the signature server-side before trusting claims, because a decoded payload provides visibility into what the token contains but zero proof that the issuer actually created it.4

Inspecting in the browser is the debugging layer; server-side verification is the security layer. Both steps serve different purposes and neither replaces the other, which is why production applications should always include a verification step even after the development team has confirmed the token shape through inspection. CapyToolkit's offline decoder fits the first role perfectly: it reads the payload locally so you can diagnose claims, algorithms, and expiry without ever exposing the token to a third-party service.

What the inspector cannot tell you

A browser JWT inspector shows the exact claims the token carries, but cannot confirm whether those claims are trustworthy. The decoded sub, role, or email values are accurate only if the issuer's private key signed the token and no character was altered in transit. An inspector that skips signature verification cannot distinguish a genuine Auth0 token from one constructed by hand with the same format, which is why the decoded payload must always be treated as unverified data until your backend confirms the cryptographic proof.4 That signature is the only thing standing between a hand-written token and a trusted one: it is what prevents an attacker from forging a token or editing the claims of an existing one, for example escalating a role from a plain user to an admin.5

For production: inspection is not authorization

For debugging, this limitation rarely matters: you control the token source and trust the content. For production access control, it matters entirely. Never route an access decision through decoded-but-unverified claims in server code. CapyToolkit's decoder is an inspection tool, not a verification tool: its value is speed during debugging, not security during authorization. After inspecting, always verify in your backend before trusting any claim the decoder displayed. A decoded payload that shows the correct sub, iss, and exp values is only genuinely trustworthy once your server has confirmed the cryptographic signature matches the issuer's published key material.

Support workflow considerations

For support workflows, ask the customer to paste only the minimum token needed for debugging, then remove it from the ticket after review. The inspector can reveal whether the token has the expected shape, but it cannot prove issuer trust. Pair that inspection with backend logs from jwtVerify so your team confirms both the claim shape and the cryptographic validity, which prevents a support agent from making authorization decisions based on unverified payload data.

Asking the customer for the minimum token needed protects their other sessions while still letting you reproduce the problem locally. The decoded shape confirms whether the issue is a missing claim or an expiry problem before you open backend logs. Closing the loop with server-side verification means support never authorises an action on inspection alone, which keeps the debugging process safe for customer data.

Use this inspector when you need to read a JWT payload during development or debugging: checking whether a claim is present, confirming an expiry time, or diagnosing a missing field without running your full backend stack. Paste a suspect token into the decoder for reading a JWT payload instantly, and read both side by side before you write a single line of debug code.

Confirming a missing claim before a server error

Paste the token and scan the payload JSON to verify whether the expected claim (e.g. email, role, or sub) is present. A missing claim in the decoded payload confirms the issue is on the issuer side, not your backend logic.

Checking token expiry during a session bug

The exp field displays as a human-readable timestamp. Compare it to the current time to determine whether the token was already expired when the error occurred.

Sources for this section
  1. 1.

    IETF, "JSON Web Token (JWT)," rfc-editor.org, accessed June 2026. https://www.rfc-editor.org/rfc/rfc7519

  2. 2.

    IETF, "JSON Web Signature (JWS)," datatracker.ietf.org, accessed June 2026. https://datatracker.ietf.org/doc/html/rfc7515

  3. 3.

    IETF, "JSON Web Algorithms (JWA)," datatracker.ietf.org, accessed June 2026. https://datatracker.ietf.org/doc/html/rfc7518

  4. 4.

    Auth0, "Validate JSON Web Tokens," auth0.com, accessed June 2026. https://auth0.com/docs/secure/tokens/json-web-tokens/validate-json-web-tokens

  5. 5.

    OWASP Cheat Sheet Series, "JSON Web Token," cheatsheetseries.owasp.org, accessed September 2026. https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_Cheat_Sheet.html

FAQ

The signature section displays the raw Base64Url-encoded signature string. An inspector does not verify the signature: it simply shows the encoded bytes. Verifying requires the signing key or the issuer's JWKS, which the inspector does not fetch.

For debugging, yes. Reading claims to diagnose a missing field or check an expiry timestamp requires only decoding. Never use unverified claims to make access control decisions. Verification is mandatory when the decoded data feeds into authorisation logic.

Yes. CapyToolkit's JWT decoder handles standard three-part JWTs from Auth0, AWS Cognito, Okta, Azure AD, Supabase, Clerk, Firebase, Keycloak, and other providers. The JWT format is standardised in RFC 7519.

Yes: anyone who obtains the raw token string can decode its header and payload. JWTs are confidentiality-protected only by controlling who receives the token, not by the encoding itself. Never include secrets in JWT payload claims.

No. The signature is a cryptographic hash of the header and payload. Reversing it to recover the secret is computationally infeasible with current algorithms. Inspecting a token reveals claims, not secrets.

Decoding in your own code

The decode this tool performs is three steps: split the token on the dots, Base64Url-decode the first two parts, and parse each as JSON. Every mainstream language can do that in a few lines without any library, which is why decoding is never the hard part of JWT work. Every language also ships JWT libraries, and their extra value is exactly the step this page deliberately does not perform: verification, where the key or key set enters the call and the signature is actually checked. Decode anywhere; verify where the keys and the authority live.

The boundary follows from what decoding needs: no secret. A decoder, in any language, proves nothing about who wrote the token, which is why a library call that only decodes is no more authoritative than this inspector. The library earns its keep at the verify call, where the signature is checked against a key you chose and the claims are checked against rules you wrote. Keep debugging with decoders, including this one, and gate access with verifiers. Confusing the two roles is how unverified claims end up trusted in production code.

Valid JWT Checklist

  • Three dot-separated Base64Url sections A JWT is always header.payload.signature — anything with a different shape is not a JWT.
  • Header names an algorithm and typ The header is a JSON object with at least alg and typ; a missing or unexpected alg is a red flag.
  • exp is a NumericDate, not a string The exp claim must be seconds since the Unix epoch — a quoted date string will not compare correctly.
  • You know this is decoding, not verifying This inspector reads the claims but does not check the signature — never trust decoded claims for access control without server-side verification.

Paste your own token above and check its header and payload against this list.

Sources
  1. 1.

    M. Jones, J. Bradley, and N. Sakimura, "JSON Web Token (JWT)," RFC 7519, IETF, May 2015. https://www.rfc-editor.org/info/rfc7519/

  2. 2.

    M. Jones, J. Bradley, and N. Sakimura, "JSON Web Signature (JWS)," RFC 7515, IETF, May 2015. https://www.rfc-editor.org/info/rfc7515/

  3. 3.

    Auth0, "JSON Web Tokens," auth0.com, accessed June 2026. https://auth0.com/docs/secure/tokens/json-web-tokens

  4. 4.

    M. Jones and D. Hardt, "The OAuth 2.0 Authorization Framework: Bearer Token Usage," RFC 6750, IETF, October 2012. https://datatracker.ietf.org/doc/html/rfc6750

  5. 5.

    Auth0, "JSON Web Token Claims," auth0.com, accessed June 2026. https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims

  6. 6.

    Spring, "JwtClaimNames (spring-security-docs 7.1.1 API)," docs.spring.io, accessed September 2026. https://docs.spring.io/spring-security/reference/api/java/org/springframework/security/oauth2/jwt/JwtClaimNames.html

  7. 7.

    D. Hardt, "The OAuth 2.0 Authorization Framework," RFC 6749, IETF, October 2012. https://datatracker.ietf.org/doc/html/rfc6749

  8. 8.

    panva, "Function: jwtVerify()," github.com, accessed June 2026. https://github.com/panva/jose/blob/main/docs/jwt/verify/functions/jwtVerify.md

  9. 9.

    PortSwigger, "JWT attacks," portswigger.net, accessed September 2026. https://portswigger.net/web-security/jwt

  10. 10.

    M. Jones, "JSON Web Key (JWK)," RFC 7517, IETF, May 2015. https://www.ietf.org/rfc/rfc7517

FAQ

No. Verifying a signature requires the secret key (for HMAC algorithms like HS256) or the public key (for RS256 or ES256). This tool decodes and inspects the contents of the token. For signature validation, use the issuer's JWKS endpoint with an appropriate library on the server side.

Yes, by design. CapyToolkit doesn't collect or transmit any token data. All decoding happens in your browser using the built-in atob() function. You can verify this yourself by disconnecting from the internet after loading the page and checking that the decoder still works.

The tool will say so. Not all JWTs include an expiry. Long-lived service tokens and API keys are sometimes issued without one. The tool displays a clear message rather than guessing.

The header specifies the signing algorithm and token type. The payload contains the actual claims: user ID, roles, expiry, and any custom fields the issuer added. Both are Base64Url-encoded, not encrypted, so anyone with the token can read the contents.

The tool compares the exp claim against your local clock. If your system clock is wrong, or if the server applies clock skew tolerance, there can be a mismatch. The token might also be missing an exp claim that the tool reports as absent rather than expired.

Yes. Once the page loads, no internet connection is needed. The entire decoding logic runs client-side.