Can You Create a JWT That Doesn’t Start with eyJ?
If you’ve worked with JSON Web Tokens (JWTs), you’ve probably noticed that they almost always start with eyJ.
Can You Create a JWT That Doesn’t Start with eyJ?
If you’ve worked with JSON Web Tokens (JWTs), you’ve probably noticed that they almost always start with eyJ.
After seeing enough of them, your brain begins to recognize eyJ... as "this is probably a JWT." At least, that's what happens to me.
But have you ever wondered whether a JWT has to start with eyJ?
It turns out the answer is no.
In this article, we’ll look at why JWTs usually start with eyJ, how to create a perfectly valid JWT that doesn't, and whether doing so is actually allowed by the specification.
Why do JWTs start with eyJ?
A JWT consists of three Base64URL-encoded parts: header.payload.signature
The header is a JSON object. Since JSON objects usually begin with {, the encoded string often starts with eyJ.
Here’s a quick demonstration using regular Base64:
$ echo "{\"a" | base64
eyJhCg==
$ echo "{\"z" | base64
eyJ6Cg==
$ echo "{\"A" | base64
eyJBCg==
$ echo "{\"Z" | base64
eyJaCg==
The first few characters change slightly, but they all begin with eyJ.
A typical JWT header looks like this:
{
"alg": "HS256",
"typ": "JWT"
}
After Base64URL encoding, the beginning is usually something like:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
So eyJ isn't a special JWT marker. It's simply what Base64URL-encoded JSON tends to look like.
What if we don’t want eyJ?
This question started as a joke.
Seeing eyJ instantly makes a string look like a JWT, and I wondered whether it would be possible to create one that didn't.
JSON allows insignificant whitespace such as spaces, tabs, and newlines. So what happens if we format the header instead of minifying it?
For example:
{
"alg": "HS256",
"typ": "JWT"
}
instead of:
{"alg":"HS256","typ":"JWT"}
Encoding the formatted version produces something like:
ewogICJhbGciOiJIUzI1NiIsCiAgInR5cCI6IkpXVCIKfQ
Notice that it starts with ewo instead of eyJ.
Looks promising!

Re-signing the token
Here’s a minimal Python example using HMAC-SHA256:
import base64
import hashlib
import hmac
SECRET_KEY = b"a-string-secret-at-least-256-bits-long"
MESSAGE = (
b"ewogICJhbGciOiJIUzI1NiIsCiAgInR5cCI6IkpXVCIKfQ."
b"eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTczNjI5MjEyNH0"
)
signature = hmac.new(
key=SECRET_KEY,
msg=MESSAGE,
digestmod=hashlib.sha256,
).digest()
print(
MESSAGE.decode()
+ "."
+ base64.urlsafe_b64encode(signature).decode().rstrip("=")
)
The resulting JWT verifies successfully, even though it no longer starts with eyJ.
Mission accomplished.
ewogICJhbGciOiJIUzI1NiIsCiAgInR5cCI6IkpXVCIKfQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTczNjI5MjEyNH0.0mg91JOJYFX7H-7COYUlzetox_qHibnvSbVBjFFBNu0

Can we go even further?
Even ewo... still feels a little JWT-ish.
What if we insert a leading space before the opening {?
That produces a header beginning with: IHS
Surprisingly, the JWT is still valid according to tools like jwt.io, as long as it is signed correctly.
At this point I started wondering whether this was actually allowed by the JWT specification.
Is this RFC-compliant?
As far as I can tell, yes.
RFC 7519 explicitly states that JSON objects may contain whitespace and/or line breaks in accordance with the JSON specification.
It also notes that:
no canonicalization need be performed before encoding.
In other words, JWT implementations are not required to remove whitespace before Base64URL encoding.
The examples in the RFC even include formatted JSON with line breaks.
So, from a specification standpoint, a JWT does not have to use a minified JSON header.
One caveat
Just because the RFC allows something doesn’t necessarily mean every library handles it correctly.
Many JWT libraries automatically serialize headers into compact JSON before signing, making it difficult — or impossible — to produce tokens like the ones shown above without constructing them manually.
Even if you manage to generate one, it’s worth testing against the JWT libraries and services you intend to use.
This article is mostly a fun experiment, not a recommendation for production systems.
Conclusion
JWTs don’t start with eyJ because the specification requires it.
They start with eyJ because most implementations serialize the header as compact JSON before Base64URL encoding.
By adding insignificant whitespace and generating a new signature, it’s possible to create perfectly valid JWTs that begin with something entirely different.
Will I ever use this in production?
Probably not.
But it’s a fun reminder that many things we think of as “part of the format” are really just conventions followed by most implementations.
메타데이터
- post_id
- 927aa9146d37
- slug
- can-you-create-a-jwt-that-doesnt-start-with-eyj-927aa9146d37
- url
- https://medium.com/@kouki_dan/can-you-create-a-jwt-that-doesnt-start-with-eyj-927aa9146d37
- canonical_url
- https://medium.com/@kouki_dan/can-you-create-a-jwt-that-doesnt-start-with-eyj-927aa9146d37
- author_url
- https://medium.com/@kouki_dan
- status
- ok
- fetched_at
- 2026-07-09 13:13:48