// adapted from https://github.com/distribution/distribution/issues/1252#issuecomment-274944254 const IMAGE = 'example/foo' const TAG = 'latest' const authorise = async () => { const url = new URL('https://auth.docker.io/token') url.searchParams.set('scope', `repository:${IMAGE}:pull`) url.searchParams.set('service', 'registry.docker.io') const response = await fetch(url) return response.json() } const { token } = await authorise() const manifest = async () => { const url = new URL( `https://registry-1.docker.io/v2/${IMAGE}/manifests/${TAG}` ) const response = await fetch(url, { headers: { Accept: 'application/vnd.docker.distribution.manifest.v2+json', Authorization: `Bearer ${token}`, }, }) return response.json() } const { config } = await manifest() const blob = async (digest) => { const url = new URL( `https://registry-1.docker.io/v2/${IMAGE}/blobs/${digest}` ) const response = await fetch(url, { headers: { Authorization: `Bearer ${token}`, }, }) return response.json() } const data = await blob(config.digest) console.log(data)