Skip to main content
Blog / JWT

How to Decode JWT Safely (Header, Payload, Signature)

Learn how to safely decode JWTs, what each part means, and where security risks arise.

DevToolsCenter Team
7 min read

Decoding reveals header and payload for inspection, but does not verify authenticity. Understanding why decoding is safe and how to do it correctly helps you debug authentication issues without compromising security.

Why decoding is safe (and why it's not verification)

JWTs use Base64URL encoding for their header and payload segments. This encoding is not encryption—it's just a way to represent JSON data as URL-safe strings. Anyone can decode a JWT without any secret, which is why decoding alone proves nothing about authenticity.

The signature segment requires cryptographic verification with the correct key, which is why you must always verify after decoding.

JWT structure explained

A JWT has three Base64URL-encoded segments separated by dots:

header.payload.signature

Header contains metadata:

  • alg: The algorithm used (e.g., HS256, RS256, ES256)
  • typ: Always "JWT" for JSON Web Tokens
  • kid: Optional key identifier for key rotation scenarios

Payload contains claims:

  • Standard claims: iss (issuer), aud (audience), sub (subject), exp (expiration), nbf (not before), iat (issued at)
  • Custom claims: Any additional data your application needs

Signature proves integrity when verified with the correct key, but decoding doesn't verify it.

Safe decoding checklist

  1. Decode client-side/offline when possible
    Use tools that run entirely in your browser, like our JWT Encoder/Decoder, so tokens never leave your device.

  2. Normalize Base64URL before raw base64 decodes
    Base64URL uses - and _ instead of + and /, and often omits padding. Convert these characters before decoding if your library expects standard Base64.

  3. Treat decoded claims as untrusted data
    Decoding reveals what someone put in the token, not what's true. Always verify the signature before trusting any claim.

  4. Redact sensitive attributes before sharing
    When debugging or creating tickets, mask user IDs, emails, and tenant identifiers to prevent data leaks.

  5. Verify signature and enforce claims in your app
    Decoding is for inspection only. Real security comes from cryptographic verification and claim validation.

How to decode safely

Browser-based (recommended)

The fastest and safest way is using our JWT Encoder/Decoder tool, which runs entirely in your browser. Paste a token and instantly see the header and payload without sending data anywhere.

Quick decode (Node.js)

function decodeJWT(token) {
  const [headerSegment, payloadSegment] = token.split('.');
  
  // Normalize Base64URL to Base64
  const normalizeBase64URL = (str) => {
    str = str.replace(/-/g, '+').replace(/_/g, '/');
    // Add padding if needed
    while (str.length % 4) {
      str += '=';
    }
    return str;
  };
  
  const decodeSegment = (segment) => {
    const normalized = normalizeBase64URL(segment);
    const decoded = Buffer.from(normalized, 'base64').toString('utf8');
    return JSON.parse(decoded);
  };
  
  return {
    header: decodeSegment(headerSegment),
    payload: decodeSegment(payloadSegment)
  };
}

// Usage
const { header, payload } = decodeJWT(token);
console.log('Algorithm:', header.alg);
console.log('Expires:', new Date(payload.exp * 1000));

Python example

import base64
import json

def decode_jwt(token):
    header_segment, payload_segment, _ = token.split('.')
    
    def decode_segment(segment):
        # Normalize Base64URL
        segment = segment.replace('-', '+').replace('_', '/')
        # Add padding
        padding = 4 - len(segment) % 4
        if padding != 4:
            segment += '=' * padding
        decoded = base64.b64decode(segment)
        return json.loads(decoded)
    
    return {
        'header': decode_segment(header_segment),
        'payload': decode_segment(payload_segment)
    }

After decoding: verification is required

Decoding shows you what's in the token, but verification proves it's authentic:

HS256 (symmetric):

  • Use your configured secret to verify
  • Same secret signs and verifies
  • Fast but requires secure secret distribution

RS256/ES256 (asymmetric):

  • Fetch JWKS from /.well-known/jwks.json
  • Select key by kid from the header
  • Build public key and verify signature
  • More secure for distributed systems

Claim enforcement:

  • Verify iss matches your configured issuer exactly
  • Check aud includes your application/client ID
  • Validate exp (not expired) and nbf (not before now)
  • Enforce custom constraints (tenant, roles, scopes)

Common pitfalls

Pitfall 1: Treating decoding as verification
Decoding a token doesn't prove it's valid. Anyone can create a JWT with any claims. Always verify the signature.

Pitfall 2: Base64URL normalization errors
Many libraries expect standard Base64. If you see "Invalid character" errors, normalize the Base64URL segments first.

Pitfall 3: Trusting decoded claims without verification
Never make authorization decisions based on decoded content alone. See our guide on why you shouldn't trust decoded JWTs for details.

When to decode vs verify

Decode when:

  • Debugging authentication issues
  • Inspecting token structure and claims
  • Understanding why verification failed
  • Learning how JWTs work

Verify when:

  • Making authentication decisions
  • Authorizing user access
  • Trusting any claim value
  • Production code paths

Next steps

  1. Try decoding a token with our JWT Encoder/Decoder to see the structure
  2. Learn about Base64URL encoding differences that cause decode failures
  3. Understand why decoding isn't verification
  4. Read our JWT troubleshooting guide for common errors

Try JWT Encoder/Decoder Now

Ready to put this into practice? Use our free JWT Encoder/Decoder tool. It works entirely in your browser with no signup required.

Launch JWT Encoder/Decoder
Free Forever No Signup Browser-Based

Frequently Asked Questions

Q Does decoding expose my token?

A

Decoding happens client-side on this site; never paste secrets into untrusted tools.