JWT Decoder & Validator avatar

JWT Decoder & Validator

Pricing

Pay per event

Go to Apify Store
JWT Decoder & Validator

JWT Decoder & Validator

Decode and validate JWT tokens in bulk. Extracts header, payload, all claims, expiration status, and validates signatures with HMAC secrets or RSA/EC public keys. Pure Node.js, no dependencies.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Decode and validate JWT (JSON Web Token) tokens in bulk. Extract the header, payload, and all standard claims in seconds — with optional signature validation using HMAC secrets or RSA/EC public keys. No external services required, no API keys, pure Node.js cryptography.

What does JWT Decoder & Validator do?

JWT Decoder & Validator decodes any valid (or malformed) JWT token and returns its full structure: algorithm, token type, kid, subject, issuer, audience, expiration time, issued-at time, and every custom claim in the payload. It also evaluates exp/nbf/iat claims to tell you instantly whether a token is expired or not yet valid.

For security audits, you can optionally supply an HMAC secret (for HS256/HS384/HS512) or a PEM public key (for RS256/RS384/RS512/ES256/ES384/ES512) to verify the signature. The actor handles bulk decoding — paste in a list of tokens and get a structured dataset back in seconds.

This tool is useful for debugging JWTs during development, auditing tokens in a CI/CD pipeline, security research, and understanding what data your tokens expose.

Who is JWT Decoder & Validator for?

Backend developers and API engineers

  • Inspecting JWTs returned by your auth service (Auth0, Cognito, Okta, Firebase, custom)
  • Debugging "token expired" errors by checking exp against server time
  • Verifying your token signing is working correctly after deploying a new key
  • Quickly reading claim values without writing a custom decode script

Security engineers and auditors

  • Bulk-auditing JWT tokens from logs or traffic captures
  • Checking whether tokens contain sensitive PII that shouldn't be in the payload
  • Validating that token expiry windows are correctly configured
  • Verifying algorithm claims match expected algorithms (detecting alg: none attacks)

DevOps and platform engineers

  • Automating token inspection in CI/CD pipelines
  • Monitoring token rotation and expiry windows
  • Integrating token validation into infrastructure-as-code workflows

Data teams and analysts

  • Extracting subject IDs and custom claims from token datasets for analysis
  • Bulk decoding tokens from exported logs to build user activity reports

Why use JWT Decoder & Validator?

  • Bulk processing — decode hundreds of tokens in a single run, not one at a time
  • No external services — pure Node.js crypto module, no third-party JWT libraries
  • Signature validation — supports HS256/384/512 (HMAC) and RS256/384/512, ES256/384/512, PS256/384/512 (asymmetric)
  • Expiration checking — evaluates exp, nbf, and iat claims accurately
  • Graceful error handling — malformed tokens produce an error field, not a crash
  • Structured output — header and payload as structured JSON objects, not raw base64
  • Dataset export — results in JSON, CSV, or Excel via Apify platform
  • API and automation ready — schedule runs, trigger via webhook, integrate with Make/Zapier

What data can you extract?

🔑 Header fields

FieldDescription
algorithmSigning algorithm (HS256, RS256, ES256, none, etc.)
header.typToken type (usually "JWT")
header.kidKey ID hint for signature verification
header.*Any custom header claims

📋 Payload / Claims

FieldDescription
subjectsub claim — the token subject (user ID, service account, etc.)
payload.issIssuer — who issued the token
payload.audAudience — intended recipient
payload.jtiJWT ID — unique token identifier
payload.*All custom claims (roles, permissions, email, name, etc.)

⏱ Time & Status

FieldDescription
issuedAtISO date string from iat claim
expiresAtISO date string from exp claim
isExpiredtrue if current time > exp, false if still valid, null if disabled
signatureValidtrue/false if secret/key provided, null if not checked

⚠️ Error handling

FieldDescription
tokenPreviewFirst 40 chars of the token for identification
errorError message if the token is malformed or unparseable

How much does it cost to decode JWT tokens?

This actor uses pay-per-event pricing — you pay only for tokens decoded. No monthly subscription. All platform costs are included.

FreeStarter ($29/mo)Scale ($199/mo)Business ($999/mo)
Per token$0.00115$0.001$0.00078$0.0006
1,000 tokens$1.15$1.00$0.78$0.60
10,000 tokens$11.50$10.00$7.80$6.00

Plus a flat $0.01 start fee per run.

Real-world cost examples:

InputTokensDurationCost (Free tier)
Single token, decode only1~2s~$0.011
50 tokens, no signature check50~3s~$0.068
1,000 tokens, with HMAC validation1,000~8s~$1.16

On the free plan ($5 credit), you can decode approximately 4,300 tokens before any payment is needed.

How to decode JWT tokens

  1. Go to JWT Decoder & Validator on Apify Store
  2. Click Try for free — no credit card required
  3. In the JWT Tokens field, paste one or more JWT tokens (one per line)
  4. Optionally enter a secret or public key under Validation Options
  5. Click Start — the run finishes in seconds
  6. Open the Dataset tab to view decoded results, then export as JSON/CSV/Excel

Example input: Single token

{
"tokens": [
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
],
"checkExpiration": true
}

Example input: Bulk + HMAC validation

{
"tokens": [
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
],
"checkExpiration": true,
"secret": "my-secret-key-minimum-256-bits"
}

Example input: RSA public key validation

{
"tokens": ["eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."],
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0B...\n-----END PUBLIC KEY-----"
}

Input parameters

ParameterTypeDefaultDescription
tokensstring[]requiredJWT token strings to decode. Duplicates are removed automatically.
checkExpirationbooleantrueEvaluate exp/nbf/iat claims and set isExpired accordingly.
secretstringHMAC secret for HS256/HS384/HS512 signature validation. Leave blank to skip.
publicKeystringPEM public key for RS256/RS384/RS512/ES256/ES384/ES512/PS256/PS384/PS512 validation. Full PEM including -----BEGIN PUBLIC KEY----- header.

Output examples

Successfully decoded token

{
"tokenPreview": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"algorithm": "HS256",
"subject": "1234567890",
"issuedAt": "2018-01-18T01:30:22.000Z",
"expiresAt": null,
"isExpired": false,
"signatureValid": true,
"header": {
"alg": "HS256",
"typ": "JWT"
},
"payload": {
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
},
"error": null
}

Expired token

{
"tokenPreview": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtp...",
"algorithm": "RS256",
"subject": "service-account",
"issuedAt": "2023-11-14T21:13:20.000Z",
"expiresAt": "2023-11-14T22:13:20.000Z",
"isExpired": true,
"signatureValid": null,
"header": { "alg": "RS256", "typ": "JWT", "kid": "key-1" },
"payload": {
"sub": "service-account",
"iss": "https://auth.example.com",
"aud": "api.example.com",
"exp": 1700000000,
"iat": 1699996400
},
"error": null
}

Malformed token

{
"tokenPreview": "notajwtatall",
"algorithm": null,
"subject": null,
"issuedAt": null,
"expiresAt": null,
"isExpired": null,
"signatureValid": null,
"header": null,
"payload": null,
"error": "Error: Invalid JWT structure: expected 3 parts separated by '.', got 1"
}

Tips for best results

  • 🔑 Provide the secret/key for full validation — without it, signatureValid returns null. Decoding still works.
  • 📋 Batch your tokens — put all tokens in one run, not one run per token. The start fee is fixed regardless of batch size.
  • 🔒 Use HMAC for HS256/HS384/HS512 — paste the raw secret string (not base64 encoded, unless your library uses base64).
  • 🔐 Use PEM for RSA/EC — copy the full PEM including -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- lines.
  • 🕰️ Disable expiration check for archived tokens where expiry is expected — set checkExpiration: false to skip.
  • ⚠️ Watch for alg: none — if a decoded header shows "alg": "none", the token has no signature. This is a known security attack vector.
  • 📁 Export to CSV for spreadsheet analysis of large token batches.

Integrations

JWT Decoder → Google Sheets workflow

  • Run the actor on a batch of tokens exported from your auth service logs
  • Export dataset as CSV → import directly to Google Sheets
  • Filter by isExpired or algorithm to audit your token inventory

JWT Decoder → Slack alert via Make.com

  • Trigger a run on new tokens detected in your monitoring system
  • Use a Make scenario to check signatureValid or isExpired fields
  • Send a Slack alert if any token fails validation

JWT Decoder → CI/CD pipeline via API

  • Call the actor from your GitHub Actions or GitLab CI pipeline
  • Validate tokens generated by your auth service during integration tests
  • Fail the pipeline if any token has signatureValid: false or unexpected claims

Scheduled token audit

  • Schedule a daily run with a rotating set of JWT tokens from your production logs
  • Monitor for tokens with unexpectedly long expiry windows or unexpected algorithms

Using the Apify API

Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('automation-lab/jwt-decoder').call({
tokens: [
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
],
checkExpiration: true,
secret: 'your-secret',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Python

from apify_client import ApifyClient
client = ApifyClient(token='YOUR_API_TOKEN')
run = client.actor('automation-lab/jwt-decoder').call(run_input={
'tokens': [
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
],
'checkExpiration': True,
'secret': 'your-secret',
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)

cURL

# Start a run
curl -X POST "https://api.apify.com/v2/acts/automation-lab~jwt-decoder/runs?token=YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tokens": ["eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."],
"checkExpiration": true
}'
# Fetch results (replace DATASET_ID with the ID from the run response)
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_API_TOKEN"

Use with AI agents via MCP

JWT Decoder & Validator is available as a tool for AI assistants that support the Model Context Protocol (MCP).

Add the Apify MCP server to your AI client — this gives you access to all Apify actors, including this one:

Setup for Claude Code

$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/jwt-decoder"

Setup for Claude Desktop, Cursor, or VS Code

Add this to your MCP config file:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/jwt-decoder"
}
}
}

Your AI assistant will use OAuth to authenticate with your Apify account on first use.

Example prompts

Once connected, try asking your AI assistant:

  • "Use automation-lab/jwt-decoder to decode this token and tell me when it expires: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  • "Decode these 5 JWT tokens and check if any of them are expired"
  • "Validate the signature on this JWT using secret 'my-secret-key' and tell me if the token is legitimate"

Learn more in the Apify MCP documentation.

JWT tokens are designed to be readable by anyone who has them — the header and payload are just base64url-encoded JSON, not encrypted. Decoding a JWT you possess is always legal.

Important: JWTs may contain personal data (names, email addresses, user IDs). When handling tokens containing PII, comply with applicable data protection laws (GDPR, CCPA, etc.). Only decode tokens you are authorized to inspect — do not decode tokens you obtained without permission.

This actor does not store, transmit, or log your tokens beyond the Apify dataset. Apify's data handling is covered by their Privacy Policy.

FAQ

Does decoding require the secret or public key? No. Decoding is always possible without any key — the header and payload are base64url-encoded JSON, not encrypted. Keys are only needed for signature validation (signatureValid). Without a key, signatureValid returns null.

What algorithms are supported for signature validation? HMAC: HS256, HS384, HS512. RSA PKCS#1: RS256, RS384, RS512. RSA-PSS: PS256, PS384, PS512. Elliptic curve: ES256, ES384, ES512. Tokens with alg: none return signatureValid: null (unsigned).

How much does it cost to decode 10,000 tokens? On the free plan: $0.01 (start) + 10,000 × $0.00115 = ~$11.51. On the Starter plan: $0.01 + 10,000 × $0.001 = ~$10.01. See the pricing section above for tier details.

Why is signatureValid returning null when I provided a secret? The algorithm in the token header (alg) must match the key type you provided. HMAC secrets are only used for HS* algorithms; PEM keys are used for RS*, ES*, and PS* algorithms. If the algorithm doesn't match the provided credential, signatureValid returns null.

Why does isExpired show true even though I just issued the token? Check your server clock — JWT expiration is evaluated against the current Unix timestamp. A few seconds of clock skew between servers can trigger this. Alternatively, check if exp in the decoded payload matches your expectation.

What happens with duplicate tokens in the input? Duplicates are automatically removed before processing. Only the first occurrence is decoded and charged.

Other developer tools