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.

More docker tools

Docker Container Image Reference Parser Is that a registry or a Docker Hub user? Dockerfile Linter What this image will do to you later docker run to Kubernetes YAML And the flags that have no equivalent Docker Compose to Kubernetes And why depends_on has no equivalent Docker Logging Driver Generator json-file never rotates Dockerfile Non-Root USER Generator Numeric, or Kubernetes rejects it Docker OCI Image Labels Generator One of them actually does something Docker Hub Pull Rate Limit Calculator Counted per IP, not per person Docker Registry Storage Calculator Deleting a tag frees nothing Docker Build Context Analyzer All of it uploads before anything runs Docker Compose to docker run Converter Names stop resolving Docker Compose Version Migrator version: is obsolete now Docker Compose Network and Port Viewer Everything reaches everything Docker Command Explainer Which flags hand over the host Docker BuildKit Cache Mount Generator apt deletes the cache you just mounted Docker BuildKit Secret Mount Generator ARG is in docker history forever Docker .dockerignore Pattern Tester *.log does not match logs/app.log Docker Image Manifest Viewer unknown/unknown is not broken Docker Image Config Viewer Anyone who can pull can read your Env Docker HEALTHCHECK Generator Docker does nothing when it fails Docker Network Subnet Calculator 31 networks, then it stops Docker History Analyzer The rm did not save anything Docker Run to Compose Converter Some flags have no equivalent Docker CMD and ENTRYPOINT Tester Why docker stop takes ten seconds Docker Port Mapping Tester -p reaches past your firewall Docker -v to --mount Converter -v invents missing directories Docker Restart Policy Simulator The backoff resets after ten seconds Docker Exit Code Explainer 137 is two different problems Docker CPU Limit Converter --cpu-shares limits nothing Docker Memory Limit Calculator -m 512m allows a gigabyte Docker Compose Interpolation Tester An unset variable is an empty string Docker Environment Variable Precedence Tester Your shell does not reach the container Docker Compose Override Merge Previewer An override can add a port, never remove one Dockerfile Multi-Stage Build Analyzer Which stages reach the image Dockerignore Validator It is not .gitignore

Elsewhere on the site