★ Dev formats · regex
Regex for JWT
A JSON Web Token in compact form: header, payload and signature separated by dots, each base64url-encoded. Headers start with eyJ because they encode '{"'. The signature can be empty for unsigned tokens.
- Runs in your browser
- No signup
Try the jwt pattern
Read it in plain English (best-effort)
- ^start of a line
- eyJthe text 'eyJ'
- [A-Za-z0-9_-]one character from: A–Z, a–z, 0–9, '_', '-'
- *zero or more of the previous
- .the character '.'
- [A-Za-z0-9_-]one character from: A–Z, a–z, 0–9, '_', '-'
- +one or more of the previous
- .the character '.'
- [A-Za-z0-9_-]one character from: A–Z, a–z, 0–9, '_', '-'
- *zero or more of the previous
- $end of a line
One sample per line works well with the m flag on anchored patterns.
The pattern, piece by piece
/^eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$/| Part | What it does |
|---|---|
^eyJ | header: base64url of '{"' |
[A-Za-z0-9_-]* | rest of the header (base64url alphabet) |
\.[A-Za-z0-9_-]+ | the payload |
\.[A-Za-z0-9_-]* | the signature, which may be empty |
What it accepts and rejects
Every sample below is checked automatically in JavaScript and Python. The tester above is preloaded with all of them, one per line.
| Should match | |
|---|---|
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c | ✓ |
eyJhbGciOiJub25lIn0.eyJzdWIiOiJhIn0. | ✓ |
eyJ0eXAiOiJKV1QifQ.eyJhIjoxfQ.abc_def-123 | ✓ |
eyJhbGciOiJFUzI1NiJ9.e30.sig | ✓ |
eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjF9.Zm9v | ✓ |
eyJraWQiOiIxIn0.eyJpc3MiOiJ4In0.c2ln | ✓ |
| Should not match | |
|---|---|
abc.def.ghi | ✗ |
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0 | ✗ |
eyJhbGciOiJIUzI1NiJ9..sig | ✗ |
eyJhbG ciOiJ9.eyJ.sig | ✗ |
eyJ+/=.e30.sig | ✗ |
Bearer eyJhbGciOiJIUzI1NiJ9.e30.sig | ✗ |
Copy it into your code
RE2-safeNo lookarounds or backreferences, so the same pattern works in Go's RE2 engine and in Rust's regex crate.
const jwtRe = /^eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$/;
export function isValidJwt(value) {
return jwtRe.test(value.trim());
}When not to use regex for this
A token that matches is not a valid token. Verify the signature, algorithm, expiry, issuer and audience with a JWT library (jose, PyJWT, golang-jwt). Never accept alg 'none' in production.
Questions engineers actually ask
Can I trust a JWT that matches this pattern?
Why must it start with eyJ?
What is catastrophic backtracking?
Sources
Formats were checked on 8 November 2026. Rules change; the official issuer wins if it disagrees.
More dev formats patterns
- UUIDRFC 9562 UUIDs, versions 1–8, with the standard variant bits.^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
- ISO 8601 DateYYYY-MM-DD dates with valid month and day ranges. Format only.^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$
- 24-hour TimeHH:MM or HH:MM:SS in 24-hour format, 00:00 to 23:59:59.^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$
- Semantic VersionThe official semver.org pattern, with pre-release and build metadata.^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
- Base64Standard padded base64: groups of four with = or == padding.^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
- MAC AddressColon, hyphen or Cisco dot notation, without mixing separators.^(?:(?:[0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}|(?:[0-9A-Fa-f]{2}-){5}[0-9A-Fa-f]{2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})$
Or browse the full regex library.
More from the workbench
Fine print
Tools: on the house.
Engineer: by the hour.
The regex was free. Code that doesn't need one is the upgrade: typed schemas, validated once at the edge, trusted everywhere after.
I'm Himanshu, an AI and full-stack engineer. I build MVPs, AI agents and the growth plumbing around them for early-stage startups.
