UNPKG is a fast, global content delivery network for everything on npm. Load any file from any package with a URL — no install, no build step:
https://unpkg.com/:package@:version/:file
:packageis the package name on npm, including scope (@scope/name).:versionis an exact version, a semver range, or a dist-tag. Omit it andlatestis used.:fileis the path to a file in the package. Omit it and UNPKG resolves the package's entry point frompackage.json(exportsfirst, thenmain; a package can choose its UNPKG default with theunpkgfield).
Examples:
- https://unpkg.com/preact@10.26.4/dist/preact.min.js
- https://unpkg.com/react@18.3.1/umd/react.production.min.js
- https://unpkg.com/three@0.174.0/build/three.module.min.js
Load a library with a classic script tag:
<script src="https://unpkg.com/preact@10.26.4/dist/preact.min.js"></script>Or build a browser app with no build step, using an import map and native ES modules:
<script type="importmap">
{
"imports": {
"preact": "https://unpkg.com/preact@10.25.4/dist/preact.module.js",
"preact/hooks": "https://unpkg.com/preact@10.25.4/hooks/dist/hooks.module.js",
"htm": "https://unpkg.com/htm@3.1.1/dist/htm.module.js"
}
}
</script>
<script type="module">
import { h, render } from "preact";
// your app here
</script>Append ?module to a package URL and UNPKG rewrites its bare imports to UNPKG URLs, so many packages work directly in a module script. For packages that are not published as browser-ready modules, esm.unpkg.com converts them first (currently in beta) — see the browser modules guide below.
Ranges and tags (preact@^10, preact@latest) redirect to the exact version they resolve to, so the response you ultimately get is always a permanent URL.
- Exact versions (e.g.
preact@10.26.4) are permanent and cache best. Bug fixes arrive only when you update the URL. - Patch-level ranges (e.g.
preact@10.26) take bug fixes within a release line automatically, while major and minor changes stay deliberate. This is a good default for production pages. - Loose ranges and tags always give you the newest matching release, at the cost of a redirect on the way in.
The security side of letting versions move is what UNPKG Shield (currently in beta) is for: it watches every npm release as it publishes and can pin or swap a compromised version at the edge before a browser executes it.
Append ?meta to any package or directory URL for JSON metadata — file paths, sizes, MIME types, and SHA-256 integrity hashes:
https://unpkg.com/react-router@7.3.0/?meta
https://unpkg.com/react-router@7.3.0/dist/?meta
Add a trailing / to a package URL (e.g. https://unpkg.com/react/) to browse its files in the package browser.
- Loading files — the URL pattern, versions, entry points, and exports
- Nobuild apps — import maps and native modules, no bundler
- Inline scripts — run TypeScript/JSX inline with the
/runhelper - Browser modules — esm.unpkg.com parameters and behavior
- Metadata API — the
?metaJSON format - Cache performance — permanent URLs and the pinning trade-off
- Supply chain security — how UNPKG Shield works, and how it differs from SRI
- Network — how files are served, cached, and verified
Machine-readable versions of the site are available for agents and crawlers: every page above is also served as Markdown (append .md to the URL, or send Accept: text/markdown), and https://unpkg.com/llms.txt indexes the full set.
This repository contains the production source for UNPKG. There are 5 packages:
unpkg-wwwis the main UNPKG website and package file CDN workerunpkg-appis the package browser app workerunpkg-esmis theesm.unpkg.compackage import worker for browser-ready ESM, CSS modules, import maps, and inline TS/TSX transformsunpkg-filesis the Bun file server backend that fetches npm tarballs, extracts files, and builds ESM artifacts for the workersunpkg-workeris the shared TypeScript library used by the workers and the files backend
We use pnpm for workspace tooling and Bun for the runtime and tests. Install these first.
Next, install all dependencies and run the tests:
pnpm install
pnpm testThen start the file server and each worker, plus the asset servers for the two HTML apps:
pnpm --filter unpkg-files dev
pnpm --filter unpkg-www dev
pnpm --filter unpkg-www dev:assets
pnpm --filter unpkg-app dev
pnpm --filter unpkg-app dev:assets
pnpm --filter unpkg-esm devThe local services listen on these ports:
unpkg-www:http://localhost:3000unpkg-app:http://localhost:3001unpkg-esm:http://localhost:3002unpkg-files:http://localhost:4000
The unpkg-files backend is deployed on Fly.io. You'll need an account.
Next, adjust the Fly config in packages/unpkg-files/fly.json (you'll need your own app name) and deploy:
pnpm --filter unpkg-files run deployTo deploy the workers, you'll need a Cloudflare account. You will also need to (1) edit the wrangler.json file in each worker and update its routes to your own domain(s) and (2) adjust each worker's environment vars (in wrangler.json) so they can find one another in production.
For API token authentication, create a local .env.local file from .env.example and set CLOUDFLARE_API_TOKEN. The worker deploy scripts load .env.local automatically before invoking Wrangler. Use a token with the Cloudflare permissions needed for the operation you are running, such as worker deploy permissions for deploys and cache purge permissions when purging CDN entries.
Once you've done that, you can deploy all workers with:
pnpm run deploy:workersOr deploy each worker individually with:
pnpm --filter unpkg-www run deploy
pnpm --filter unpkg-app run deploy
pnpm --filter unpkg-esm run deployPlease see LICENSE for more information.