npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dockerhub-api-client

v1.0.0

Published

TypeScript client for the Docker Hub REST API

Readme

dockerhub-api-client

CI npm version npm downloads/week npm downloads/month Bundle size License: MIT TypeScript Node.js

TypeScript client for the Docker Hub REST API. Query repository metadata, image tags, user profiles, organizations, and search — from Node.js or the browser. Fully typed, zero runtime dependencies.


Installation

npm install dockerhub-api-client

Quick start

import { DockerHubClient } from 'dockerhub-api-client';

// Public API — no auth required
const hub = new DockerHubClient();

// Authenticated — required for private repos
const token = await hub.login('myuser', 'mypassword');
const authedHub = new DockerHubClient({ token });

// Custom API URL (mirrors / private registries)
const hub = new DockerHubClient({ apiUrl: 'https://hub.docker.com/v2' });

API reference

Repository metadata

// Await directly — fetches repository metadata
const repo = await hub.repository('library', 'nginx');
const repo = await hub.repository('library', 'nginx').get(); // same

console.log(repo.name);         // 'nginx'
console.log(repo.namespace);    // 'library'
console.log(repo.description);  // 'Official build of Nginx.'
console.log(repo.pull_count);   // 1000000000
console.log(repo.star_count);   // 18000
console.log(repo.is_private);   // false
console.log(repo.last_updated); // '2024-01-01T00:00:00.000000Z'

For official Docker Hub images (nginx, node, python, etc.) use 'library' as the namespace.

Image tags

// List all tags (first page)
const { results, count, hasNextPage, nextPage } = await hub.repository('library', 'nginx').tags();

console.log(count);       // total tags
console.log(hasNextPage); // true
console.log(nextPage);    // 2

results.forEach(tag => {
  console.log(tag.name);         // 'latest', '1.25.3-alpine', ...
  console.log(tag.digest);       // 'sha256:abc123...'
  console.log(tag.full_size);    // compressed size in bytes
  console.log(tag.last_updated); // ISO timestamp
});

// Pagination
const page2 = await hub.repository('library', 'nginx').tags({ page: 2, page_size: 25 });

// Filter by name prefix
const alpine = await hub.repository('library', 'nginx').tags({ name: 'alpine' });

// Per-platform details
results.forEach(tag => {
  tag.images.forEach(img => {
    console.log(`${img.os}/${img.architecture}`); // 'linux/amd64', 'linux/arm64'
    console.log(img.digest);                      // platform-specific digest
    console.log(img.size);                        // uncompressed size in bytes
    console.log(img.status);                      // 'active'
  });
});

User profile

// Await directly — fetches user profile
const user = await hub.user('johndoe');
const user = await hub.user('johndoe').get(); // same

console.log(user.username);    // 'johndoe'
console.log(user.full_name);   // 'John Doe'
console.log(user.type);        // 'User'
console.log(user.date_joined); // '2023-01-01T00:00:00.000000Z'

User repositories

const { results, count } = await hub.user('johndoe').repositories();
const { results, count } = await hub.user('johndoe').repositories({ page_size: 25 });

console.log(`${count} total repositories`);
results.forEach(r => {
  console.log(r.name, r.pull_count, r.is_private);
});

Organization

const org = await hub.org('docker');

console.log(org.orgname);    // 'docker'
console.log(org.full_name);  // 'Docker, Inc.'
console.log(org.type);       // 'Organization'

Search

const { results, count, hasNextPage } = await hub.search({ query: 'nginx' });
const { results } = await hub.search({ query: 'nginx', page_size: 10 });
const { results } = await hub.search({ query: 'nginx', page: 2, page_size: 25 });

console.log(`${count} total results`);
results.forEach(r => {
  console.log(r.repo_name);          // 'library/nginx'
  console.log(r.short_description);  // 'Official build of Nginx.'
  console.log(r.is_official);        // true
  console.log(r.star_count);         // 18000
  console.log(r.pull_count);         // 1000000000
});

Authentication

// Obtain a JWT token from username + password (or personal access token)
const token = await hub.login('myuser', 'mypassword');

// Pass it to a new client instance
const authedHub = new DockerHubClient({ token });

// All subsequent requests include: Authorization: JWT <token>
const privateRepo = await authedHub.repository('myorg', 'private-image').get();

Chainable resource pattern

Every resource implements PromiseLike, so you can await it directly or chain methods:

// Await directly → fetches repository metadata
const repo = await hub.repository('library', 'nginx');

// Chain → fetches tags
const tags = await hub.repository('library', 'nginx').tags({ page_size: 5 });

// Await directly → fetches user profile
const user = await hub.user('johndoe');

// Chain → fetches their repositories
const repos = await hub.user('johndoe').repositories();

Cancelling requests

Pass an AbortSignal to any method to cancel the in-flight request:

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

await hub.repository('library', 'nginx').get(controller.signal);
await hub.repository('library', 'nginx').tags({ page_size: 10 }, controller.signal);
await hub.user('johndoe').get(controller.signal);
await hub.user('johndoe').repositories({}, controller.signal);
await hub.org('docker', controller.signal);
await hub.search({ query: 'nginx' }, controller.signal);
await hub.login('user', 'pass', controller.signal);

When aborted, fetch throws a DOMException with name === 'AbortError'. The request event is still emitted with the error attached.


Request events

Subscribe to every HTTP request for logging, monitoring, or debugging:

hub.on('request', (event) => {
  console.log(`[${event.method}] ${event.url} → ${event.statusCode} (${event.durationMs}ms)`);
  if (event.error) {
    console.error('Request failed:', event.error.message);
  }
});

Supports method chaining: hub.on('request', handler).on('request', anotherHandler).

| Field | Type | Description | | --- | --- | --- | | url | string | Full URL that was requested | | method | 'GET' \| 'POST' | HTTP method used | | startedAt | Date | When the request started | | finishedAt | Date | When the request finished | | durationMs | number | Duration in milliseconds | | statusCode | number \| undefined | HTTP status code, if a response was received | | error | Error \| undefined | Present only if the request failed |


Error handling

Non-2xx responses throw a DockerHubApiError with the HTTP status code and status text:

import { DockerHubApiError } from 'dockerhub-api-client';

try {
  await hub.repository('library', 'nonexistent-image').get();
} catch (err) {
  if (err instanceof DockerHubApiError) {
    console.log(err.status);     // 404
    console.log(err.statusText); // 'Not Found'
    console.log(err.message);    // 'Docker Hub API error: 404 Not Found'
  }
}

Pagination

All list methods return a DockerHubPagedResponse<T>:

const page1 = await hub.repository('library', 'nginx').tags({ page_size: 25 });

console.log(page1.results);     // tag items on this page
console.log(page1.count);       // total number of tags across all pages
console.log(page1.hasNextPage); // true / false
console.log(page1.nextPage);    // 2 (page number), or undefined

// Fetch next page
if (page1.hasNextPage) {
  const page2 = await hub.repository('library', 'nginx').tags({
    page: page1.nextPage,
    page_size: 25,
  });
}

// Collect all pages
async function fetchAllTags(namespace: string, name: string) {
  const all = [];
  let page = 1;
  while (true) {
    const { results, hasNextPage } = await hub.repository(namespace, name).tags({ page, page_size: 100 });
    all.push(...results);
    if (!hasNextPage) break;
    page++;
  }
  return all;
}

TypeScript types

All domain types are exported:

import type {
  // Client
  DockerHubClientOptions,
  RequestEvent,
  DockerHubClientEvents,

  // Repository
  DockerHubRepository,
  DockerHubRepositoryPermissions,
  DockerHubRepositoriesParams,

  // Tags
  DockerHubTag,
  DockerHubImageDetail,
  DockerHubTagsParams,

  // User
  DockerHubUser,

  // Organization
  DockerHubOrganization,

  // Search
  DockerHubSearchResult,
  DockerHubSearchParams,

  // Pagination
  DockerHubPagedResponse,
  DockerHubPaginatedResponse,
} from 'dockerhub-api-client';

Documentation

Full API documentation is published at: https://eljijuna.github.io/dockerhub-api-client


Contributing

See CONTRIBUTING.md.


License

MIT