Docker Registry Token Decoder

See what a registry token actually grants. A failed pull is far more often a scope problem than an authentication problem, and the scope is written inside the token.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Decode. Nothing leaves this tab.

Wanted a different tool?

  • JWT Decoder & Inspector if the token is not a registry one, because that reads any JWT and does not try to interpret scopes.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A push token

Push means it can replace a tag, which is enough to change what gets deployed

{"token":"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjaS1ib3QiLCJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6ImFjbWUvYXBwIiwiYWN0aW9ucyI6WyJwdWxsIiwicHVzaCJdfV19.sig"}

An anonymous token

Rate limited per source IP, which a shared CI pool exhausts collectively

eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIiLCJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6ImxpYnJhcnkvYWxwaW5lIiwiYWN0aW9ucyI6WyJwdWxsIl19XX0.sig

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Re-checking credentials after a failed pull

    A 401 is authentication and a 403 is scope. If a token was issued at all, the credentials worked and the problem is what it grants.

    Instead:Decode it and compare the access claims against the repository you are pulling.

  2. Pulling public images anonymously in CI

    The anonymous rate limit is counted per source IP, so a shared runner pool exhausts it collectively and pulls start failing for everybody.

    Instead:Authenticate even for public images. The limit is then per account and much higher.

  3. Pasting a token into an issue to ask for help

    It is a working credential until it expires, and issue trackers keep history and send email.

    Instead:Paste the decoded claims instead. Nothing in them is secret.

A 401 is authentication and a 403 is scope

The token you get back can be perfectly valid and grant nothing. Reading the access claims is faster than re-checking credentials that were never wrong.

The access claims are the answer

Each one is a type, a repository name and a list of actions. A pull needs pull on that exact repository name, spelled as the registry has it, including the library/ prefix on Docker Hub official images. An empty access array means the requested scope matched nothing the account may reach.

A token that can push can replace a tag

Tags are mutable, so push access to a repository is enough to have a different image deployed the next time anything pulls, with nothing visible in any repository. Treat a token carrying push like a deploy key.

An anonymous token is rate limited per IP address

With no subject the registry issued it without authentication. On Docker Hub that means the anonymous limit, counted per source address, so a NAT gateway or a CI runner pool shares one budget across everybody behind it. Authenticating even for public images moves you to a higher limit counted per account.

Not every registry issues a JWT

The v2 spec does not require one. Several registries and proxies return an opaque string that means something only to the issuer, in which case the scope is whatever was requested rather than something the token states.

The signature is not checked here

Verifying it needs the registry's public key, which means a network request this page deliberately does not make. So these are the claims the token makes, which is what you want when working out why a pull was refused, and not proof it is genuine.

This is a credential

For as long as it is valid, anybody holding it can do whatever the scope allows with no further authentication. Decoding it here is safe because nothing leaves the tab. Pasting it into a ticket or a chat is not.