★ Dev formats · regex
Regex for Base64
Matches standard (RFC 4648) base64 with correct padding. The empty string also matches, which is valid base64 for empty data. For base64url, swap + and / for - and _.
- Runs in your browser
- No signup
Try the base64 pattern
Read it in plain English (best-effort)
- ^start of a line
- (?:start a group (not captured)
- [A-Za-z0-9+/]one character from: A–Z, a–z, 0–9, '+', '/'
- {4}exactly 4 of the previous
- )end of group
- *zero or more of the previous
- (?:start a group (not captured)
- [A-Za-z0-9+/]one character from: A–Z, a–z, 0–9, '+', '/'
- {2}exactly 2 of the previous
- ==the text '=='
- |or
- [A-Za-z0-9+/]one character from: A–Z, a–z, 0–9, '+', '/'
- {3}exactly 3 of the previous
- =the character '='
- )end of group
- ?the previous is optional
- $end of a line
One sample per line works well with the m flag on anchored patterns.
The pattern, piece by piece
/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/| Part | What it does |
|---|---|
(?:[A-Za-z0-9+/]{4})* | full groups of four base64 characters |
[A-Za-z0-9+/]{2}== | a final group with two padding characters |
|[A-Za-z0-9+/]{3}= | or a final group with one padding character |
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 | |
|---|---|
SGVsbG8= | ✓ |
SGVsbG8gV29ybGQ= | ✓ |
YQ== | ✓ |
YWI= | ✓ |
YWJj | ✓ |
U29tZSBsb25nZXIgdGV4dCE+Lw== | ✓ |
| Should not match | |
|---|---|
SGVsbG8 | ✗ |
YQ= | ✗ |
Y=== | ✗ |
SGV sbG8= | ✗ |
SGVsbG8=$ | ✗ |
YWJj= | ✗ |
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 base64Re = /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/;
export function isValidBase64(value) {
return base64Re.test(value.trim());
}When not to use regex for this
The simplest check is to decode it. atob() in JavaScript or base64.b64decode(…, validate=True) in Python fail loudly on bad input.
Questions engineers actually ask
Why does the empty string match?
Does it accept unpadded base64?
What is catastrophic backtracking?
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-]+)*))?$
- JWTThree base64url segments starting with eyJ. Shape only, never trust it.^eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$
- 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.
