# What the Web Actually Runs On: jsDelivr Says a Korean Font, Not React

A Korean webfont was jsDelivr&#39;s single biggest bandwidth consumer in June 2026 at 16.0% of the whole network. React ranked #535. What a CDN byte ranking really measures.

Author: J.A. Watte
Published: July 15, 2026
Source: https://jwatte.com/blog/jsdelivr-top-packages-edge-proxy-builds/

---

I expected jsDelivr's bandwidth leaderboard to read like a roll call of the usual suspects: jQuery, React, Vue, Font Awesome, three.js, axios, lodash, core-js. I pulled the live stats API on 15 July 2026 for the complete month of June 2026, and not one of those is in the top 15 by bandwidth. Not for npm, not for GitHub.

The single largest bandwidth consumer on the entire network is a typeface. `gh/orioncactus/pretendard`, a Korean, Latin and Japanese webfont, served 3,099.55 TB in June 2026, which is 16.0% of all jsDelivr bandwidth for the month ([stats API](https://data.jsdelivr.com/v1/stats/packages?period=2026-06&type=gh&by=bandwidth&limit=20)). React ranks #535 by bandwidth. core-js ranks #4,650.

That pair of facts is the whole article in miniature. A CDN byte ranking does not measure what the web is built on. It measures **what gets shipped over that specific CDN as raw bytes**. Anything that gets bundled by a build tool or self-hosted is nearly invisible, and anything big and binary dominates. Once you accept that, the leaderboard becomes genuinely useful, just not for the question you thought you were asking.

## Method, so you can re-run it

All figures below come from the jsDelivr public stats API, fetched 15 July 2026, for the fixed period `2026-06`. Bytes are converted with TB = 10^12 (decimal); the raw integers are what the API returns.

Three API details that will bite you. First, `/v1/stats/packages` **defaults to sorting by hits, not bandwidth**. The obvious-looking call `?period=month&type=npm` returns swiper first, which is hits order. Pass `&by=bandwidth` explicitly or you silently get the wrong leaderboard. The [OpenAPI spec](https://data.jsdelivr.com/v1/spec.yaml) is the authority on params; the API root itself returns HTTP 400, so do not cite it as docs.

Second, on the per-package endpoint, `rank` and `typeRank` are **zero-indexed**. Pretendard comes back as `bandwidth.rank=0` while being first in the ordered list. Print that raw and you publish an off-by-one. Every rank here is already converted to 1-based.

Third, use the fixed period `2026-06`, not `period=month`. `month` is a rolling window and it drifts: on my re-check, hls.js was 973.68 TB fixed and 1,012.05 TB rolling.

## Table A: top 15 npm packages by bandwidth

Fetched 15 July 2026, period 2026-06. Source: [stats API, npm by bandwidth](https://data.jsdelivr.com/v1/stats/packages?period=2026-06&type=npm&by=bandwidth&limit=20).

| # | package | TB (10^12) | hits (B) | avg/req | what it is |
|---|---|---|---|---|---|
| 1 | hls.js | 973.68 | 6.40 | 148.6 KB | HLS video player |
| 2 | @lottiefiles/dotlottie-web | 595.69 | 1.09 | 533.7 KB | vector animation player |
| 3 | bootstrap | 415.41 | 15.43 | 26.3 KB | the CSS framework |
| 4 | swiper | 375.91 | 18.91 | 19.4 KB | touch slider, most hits of any npm package |
| 5 | pretendard | 306.83 | 0.59 | 508.1 KB | the webfont, npm copy |
| 6 | bootstrap-icons | 250.18 | 4.74 | 51.6 KB | SVG icon library |
| 7 | @mediapipe/tasks-vision | 201.76 | 0.17 | 1141.3 KB | on-device computer vision |
| 8 | mathjax | 188.83 | 2.84 | 65.0 KB | math typesetting |
| 9 | prebid.js | 172.36 | 0.26 | 654.6 KB | header bidding, ad tech |
| 10 | @mdi/font | 172.10 | 1.35 | 124.9 KB | Material Design icon font |
| 11 | yandex-metrica-watch | 166.24 | 1.53 | 106.0 KB | analytics shim |
| 12 | opencc-js | 159.92 | 1.10 | 142.3 KB | Chinese script conversion |
| 13 | monaco-editor | 115.11 | 0.58 | 193.4 KB | the VS Code editor core |
| 14 | onnxruntime-web | 102.72 | 0.05 | 2069.5 KB | ONNX models in the browser |
| 15 | video.js | 96.83 | 1.18 | 80.4 KB | HTML5 video player |

Package identities are confirmed against the [npm registry](https://registry.npmjs.org/hls.js). Read that table again and notice what it is: video players, fonts, icon sets, ad tech, an analytics shim, a CJK text converter, and two AI runtimes. Bootstrap and Swiper are the only "classics" left standing.

Here is where the rest of them actually land for June 2026, by bandwidth, 1-based, overall then npm-only ([per-package stats](https://data.jsdelivr.com/v1/stats/packages/npm/jquery?period=2026-06)): jquery 58.05 TB (#53/#24), vue 54.52 TB (#56/#26), chart.js 53.29 TB (#59/#29), @fortawesome/fontawesome-free 48.74 TB (#64/#33), three 34.26 TB (#87/#46), axios 15.76 TB (#155/#85), lodash 6.90 TB (#291/#163), [react](https://data.jsdelivr.com/v1/stats/packages/npm/react?period=2026-06) 2.73 TB (#535/#293), core-js 0.04 TB (#4650/#2261).

React and core-js are two of the most depended-upon packages in the npm ecosystem and they are functionally absent. They get bundled. That is the cleanest available proof that bandwidth rank is not popularity.

## Why the ranking looks like this

Bandwidth rank is approximately file size multiplied by popularity, and nothing else. Measured over the wire on 15 July 2026:

* `PretendardVariable.woff2` is **2,057,688 bytes** per download. That one file served 469.75 TB in June 2026.
* `Pretendard-Regular.woff2` is 765,892 bytes and served 422.49 TB.
* `easylist.txt` from uBlockOrigin/uAssetsCDN is 2,119,132 bytes and served 296.12 TB.
* `hls.min.js` in hls.js@1.6.16, the version that drove 87.25% of that package's traffic, is 543,002 bytes and served 848.04 TB by itself.
* `bootstrap.min.css` 5.3.8 is 232,111 bytes.

So Swiper has almost three times hls.js's hits (18.91B vs 6.40B) and ships 2.6x fewer bytes. If you print one column you mislead. [Pretendard](https://github.com/orioncactus/pretendard) is a system-ui alternative blending Inter, Source Han Sans and the M+ Japanese face, released under the SIL Open Font License in nine weights plus a variable, and used by Naver Webtoon, Kakao Bank, Wanted, Musinsa, Class101, Inflearn and Adobe Fonts. Megabytes of font, at Korean-internet scale. That is the whole mechanism. (Counting all four Pretendard-related entries reaches roughly 20.6% of the network, but that aggregation is my own analytical choice, not a jsDelivr-published figure. The single defensible number is the 16.0% above.)

## Table B: top 15 GitHub repos by bandwidth, and the part nobody advertises

Fetched 15 July 2026, period 2026-06. Repo existence re-checked via api.github.com the same day. Source: [stats API, GitHub by bandwidth](https://data.jsdelivr.com/v1/stats/packages?period=2026-06&type=gh&by=bandwidth&limit=20).

| # | repo | TB | hits (B) | avg/req | what it is / status |
|---|---|---|---|---|---|
| 1 | orioncactus/pretendard | 3099.55 | 20.02 | 151.2 KB | the webfont. 16.0% of the whole network |
| 2 | uBlockOrigin/uAssetsCDN | 620.84 | 2.06 | 294.5 KB | adblock filter lists pulled by browser extensions |
| 3 | adop-devel/jsdelivr | 420.78 | 0.75 | 548.2 KB | 0 stars. Re-hosts Pretendard .woff files |
| 4 | fonts-archive/AppleSDGothicNeo | 203.69 | 0.19 | 1055.3 KB | 4 stars. Korean font archive |
| 5 | Lexusbro/dummy | 180.59 | 0.29 | 610.8 KB | **GitHub repo 404.** One file, /dummy1.txt = 108.31 TB |
| 6 | fonts-archive/Pretendard | 174.11 | 0.25 | 666.9 KB | 16 stars. Another Pretendard mirror |
| 7 | msalvatorius/gladio | 166.92 | 0.05 | 3097.2 KB | 0 stars. Raw MP4 video |
| 8 | Project-Noonnu/noonfonts_2107 | 165.82 | 0.15 | 1113.2 KB | 0 stars. Korean font collection |
| 9 | genizy/web-port | 141.33 | 0.03 | 5237.2 KB | 147 stars, "web port of pc games". Game .pck assets |
| 10 | hgkukigtfhnujh6-ops/extra | 128.53 | 0.04 | 3162.6 KB | 0 stars, no description. Randomly named hashed JS |
| 11 | hgkukigtfhnujh6-ops/temp | 128.36 | 0.04 | 3136.0 KB | same throwaway account as #10 |
| 12 | shuvoads24-eng/azree2 | 96.01 | 0.03 | 3293.5 KB | **GitHub repo 404** |
| 13 | shuvoads24-eng/azree1 | 95.98 | 0.03 | 3271.9 KB | **GitHub repo 404** |
| 14 | ayanjuwel/love_my_bou | 92.78 | 2.72 | 33.3 KB | 0 stars. /live.json = 70.35 TB |
| 15 | ahsdev22-png/temp | 89.98 | 0.03 | 3086.0 KB | 0 stars. Randomly named hashed JS |

jsDelivr's [Terms of Use](https://raw.githubusercontent.com/jsdelivr/jsdelivr/master/Terms%20of%20Use.md) contain an Acceptable Use Policy prohibiting "using jsDelivr CDN as a general-purpose file or media hosting service", with the examples "running an image hosting website and using jsDelivr CDN as a storage for all uploaded images, hosting videos, file backups, or other files in large quantities."

Several rows above are exactly that. `msalvatorius/gladio` (166.92 TB, 3.1 MB average per request) serves `/0416.mp4` at 77.36 TB and two more MP4s behind it. `Lexusbro/dummy` shipped 180.59 TB from a single text file. `ayanjuwel/love_my_bou` serves `/live.json` for 70.35 TB, a live sports-score feed polled as a free API backend. And a cluster of zero-star, no-description accounts named `temp` and `extra` is pushing randomly-named hashed JavaScript at about 3 MB a request. I did not download or analyse any of those payloads, so I am describing a pattern, not making a claim about what the code does. That is as far as the evidence goes.

Two rows deserve care. `genizy/web-port` is probably fine: the same AUP says "We recognize that there are legitimate projects that consist of a large number of files, and these are not considered abuse. For example: icons packs, apps, or games with a large number of assets." And uBlockOrigin/uAssetsCDN at 620.84 TB is not the web loading a library at all. It is millions of browser extensions fetching filter lists on a schedule.

The strongest fact in the table: **three of the top 15 GitHub repos by bandwidth no longer exist on GitHub.** Lexusbro/dummy, shuvoads24-eng/azree1 and azree2 all return 404 from [api.github.com](https://api.github.com/repos/shuvoads24-eng/azree2) as of 15 July 2026, and the entire `shuvoads24-eng` account is gone too. That is 372.58 TB of June traffic attributable to repositories that have since vanished. Separately, June 2026 bandwidth fell 13.2% month over month (19.37 PB against 22.32 PB) while hits rose 1.7% ([network stats](https://data.jsdelivr.com/v1/stats/network?period=2026-06)). Bytes down, requests up. I found no jsDelivr announcement explaining it, so I am not going to claim a cause.

## Table C: top 15 GitHub repos by hits, because ranking flips

Fetched 15 July 2026, period 2026-06. Source: [stats API, GitHub by hits](https://data.jsdelivr.com/v1/stats/packages?period=2026-06&type=gh&by=hits&limit=20).

| # | repo | hits (B) | TB | avg/req |
|---|---|---|---|---|
| 1 | prebid/currency-file | 40.46 | 58.37 | 1.4 KB |
| 2 | orioncactus/pretendard | 20.02 | 3099.55 | 151.2 KB |
| 3 | prebid/shared-id | 10.86 | 8.29 | 0.7 KB |
| 4 | lipis/flag-icons | 2.89 | 7.64 | 2.6 KB |
| 5 | ayanjuwel/love_my_bou | 2.72 | 92.78 | 33.3 KB |
| 6 | foyer-work/cdn-files | 2.35 | 1.45 | 0.6 KB |
| 7 | twitter/twemoji | 2.33 | 3.21 | 1.3 KB |
| 8 | jdecked/twemoji | 2.14 | 3.41 | 1.6 KB |
| 9 | uBlockOrigin/uAssetsCDN | 2.06 | 620.84 | 294.5 KB |
| 10 | piedotorg/pie-adblock-rules | 1.52 | 1.80 | 1.2 KB |
| 11 | spbgovbr-vlibras/vlibras-portal | 1.46 | 81.55 | 54.4 KB |
| 12 | prebid/prebid-mobile-ios | 1.20 | 14.17 | 11.6 KB |
| 13 | fancyapps/fancybox | 0.85 | 13.31 | 15.3 KB |
| 14 | adop-devel/jsdelivr | 0.75 | 420.78 | 548.2 KB |
| 15 | jimaek/testobjects | 0.72 | 32.17 | 43.5 KB |

The number one repository by request count is an ad-tech currency file, at 40.46 billion requests of 1.4 KB each. Prebid takes three of the top 12. Those are ad auctions, not developers. Fourth is a country-flag SVG set; eleventh is a Brazilian government sign-language accessibility portal. On the npm side by hits, swiper (18.91B) and bootstrap (15.43B) lead, and slick-carousel, a jQuery-era carousel, is still at 6.75B.

Network-wide for June 2026: 346,742,743,884 requests and 19,372,012,771,308,052 bytes, which is 19,372 TB, or 19.37 PB. Packages accounted for 98.08% of the bandwidth. Only two CDN providers reported traffic, Fastly at 55.2% of bytes and Cloudflare at 44.8%, though jsDelivr [documents](https://raw.githubusercontent.com/jsdelivr/jsdelivr/master/Sub-Processors.md) a multi-CDN arrangement using Cloudflare, Fastly and Gcore "to serve jsDelivr CDN traffic", with "#### Bunny (Limited to legacy bootstrapcdn.com CDN endpoints)".

## What this changes about how you load things

A CDN URL is a supply-chain decision with a measurable cache consequence. Both halves are testable.

**Pin the exact version.** I measured the response headers on 15 July 2026:

| URL shape | Cache-Control returned |
|---|---|
| `/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css` | `public, max-age=31536000, s-maxage=31536000, immutable` |
| `/npm/bootstrap@5/...` | `public, max-age=604800, s-maxage=43200` |
| `/npm/bootstrap@latest/...` | `public, max-age=604800, s-maxage=43200` |
| `/npm/bootstrap/...` | `public, max-age=604800, s-maxage=43200` |

A pinned version is cached for a year and marked immutable. A floating range gets seven days in the browser and twelve hours at the edge. Pinning is a security control that also happens to be a materially better cache.

**SRI and floating ranges fail in the nastiest possible way.** Right now `/npm/bootstrap@5/dist/css/bootstrap.min.css` is byte-identical to `@5.3.8`: both 232,111 bytes, both hashing to `sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB`, which reproduces [Bootstrap's published integrity value](https://getbootstrap.com/docs/5.3/getting-started/introduction/) exactly. So an SRI hash on a range works today, and then silently breaks the moment the range resolves to a new release, at which point the browser blocks the resource and your page breaks with no warning. Bootstrap's current documented version is 5.3.8, incidentally, not the 5.3.3 that AI assistants tend to emit from memory.

**And SRI does not work on generated files at all, even pinned ones.** jsDelivr's own `+esm` output carries the inline comment "Do NOT use SRI with dynamically generated files!" The [reason](https://www.jsdelivr.com/using-sri-with-dynamic-files) is that "Minifying the exact same source code multiple times might not result in the exact same generated code", and "we might need to re-minify the file in certain situation, e.g., as a part of failover". Pinning fixes the version. It does not make a generated artifact byte-stable. So the "no build step" convenience and SRI are mutually exclusive. Pick knowingly.

Why any of this matters: polyfill.io. Cloudflare [warned publicly on 29 February 2024](https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk/) about "the transition of the domain polyfill.io to a new provider (Funnull)", noting that any site embedding the original domain "will now be relying on Funnull to maintain and secure the underlying project to avoid the risk of a supply chain attack." [Sansec reported the malware on 25 June 2024](https://sansec.io/research/polyfill-supply-chain-attack): 100,000+ sites affected including JSTOR, Intuit and the World Economic Forum, with injected code that "redirects mobile users to a sports betting site using a fake Google analytics domain", activates only on specific mobile devices at specific hours, and stays dormant when it detects an admin user. Four months between the warning and the confirmed compromise. The domain changed hands; the script tags did not.

## Building on it: the two-line version

The `+esm` path genuinely works. I downloaded `https://cdn.jsdelivr.net/npm/nanoid@5.0.7/+esm` and imported it in Node 24.15.0; it executed and exposed real named exports.

{% raw %}
```html
<script type="module">
  // Pin the exact version. No build step, no bundler.
  const { nanoid } = await import("https://cdn.jsdelivr.net/npm/nanoid@5.0.7/+esm");
  document.querySelector("#id").textContent = nanoid();

  // Lazy-load only on demand:
  document.querySelector("#celebrate").addEventListener("click", async () => {
    const confetti = (await import("https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/+esm")).default;
    confetti();
  });
</script>
```
{% endraw %}

Two live-tested gotchas. The `/combine` endpoint **requires full file paths**: `/combine/npm/canvas-confetti@1.9.3,npm/nanoid@5.0.7` returns 404, while `/combine/npm/canvas-confetti@1.9.3/dist/confetti.browser.js,npm/nanoid@5.0.7/index.browser.js` returns 200. And `esm.run` is jsDelivr's ESM service but it is [still beta](https://www.jsdelivr.com/esm): "You can use esm.run links for quick demos or prototyping. In production (once this feature is out of beta), always use our main domain."

If you allow-list jsDelivr in CSP, know what you bought:

```
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' https://cdn.jsdelivr.net;
font-src https://cdn.jsdelivr.net;
connect-src 'self' https://your-proxy.workers.dev;
```

CSP allow-lists the **host**, so that authorizes all of jsDelivr, not your specific file. That is precisely why SRI (byte-level) and CSP (host-level) are complementary rather than substitutes.

## Building on it: the edge proxy, with the guardrails included

The moment you build a real tool on top of someone's API you want your own front door: caching, timeouts, a budget. Here is a Cloudflare Worker CORS proxy that does not become an open relay. It passes `node --check` and a 16-case test suite I ran locally, including a blocked open-relay attempt, a blocked subdomain-suffix bypass, a blocked cloud-metadata IP, a 429, and a 413 on an oversized body with no `Content-Length`.

{% raw %}
```js
const ALLOWED_ORIGINS = new Set(["https://yourtool.example", "http://localhost:8788"]);
const ALLOWED_TARGET_HOSTS = new Set(["api.example.com", "data.jsdelivr.com"]);
const TIMEOUT_MS = 8000;
const MAX_BYTES = 2 * 1024 * 1024;
const CACHE_TTL_SECONDS = 300;

function corsHeaders(origin) {
  return {
    "Access-Control-Allow-Origin": origin,
    "Access-Control-Allow-Methods": "GET, OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type",
    "Access-Control-Max-Age": "86400",
    Vary: "Origin",
  };
}
function deny(status, message, origin) {
  const headers = { "Content-Type": "application/json" };
  if (origin) Object.assign(headers, corsHeaders(origin));
  return new Response(JSON.stringify({ error: message }), { status, headers });
}
export default {
  async fetch(request, env, ctx) {
    const origin = request.headers.get("Origin") ?? "";
    const allowedOrigin = ALLOWED_ORIGINS.has(origin) ? origin : null;
    // Preflight is answered FIRST, or the browser blocks the real request.
    if (request.method === "OPTIONS") {
      if (!allowedOrigin) return new Response(null, { status: 403 });
      return new Response(null, { status: 204, headers: corsHeaders(allowedOrigin) });
    }
    if (!allowedOrigin) return deny(403, "origin_not_allowed", null);
    if (request.method !== "GET") return deny(405, "method_not_allowed", allowedOrigin);
    const target = new URL(request.url).searchParams.get("url");
    if (!target) return deny(400, "missing_url_param", allowedOrigin);
    let targetUrl;
    try { targetUrl = new URL(target); } catch { return deny(400, "invalid_url", allowedOrigin); }
    if (targetUrl.protocol !== "https:") return deny(400, "https_only", allowedOrigin);
    // Exact match. NEVER endsWith(): "api.example.com.attacker.test".endsWith("example.com") is true.
    if (!ALLOWED_TARGET_HOSTS.has(targetUrl.hostname)) return deny(403, "target_not_allowed", allowedOrigin);
    const ip = request.headers.get("CF-Connecting-IP") ?? "unknown";
    if (env.RATE_LIMITER) {
      const { success } = await env.RATE_LIMITER.limit({ key: ip });
      if (!success) return deny(429, "rate_limited", allowedOrigin);
    }
    const cacheKey = new Request(`https://proxy.internal/${encodeURIComponent(targetUrl.toString())}`, { method: "GET" });
    const cache = caches.default;
    const cached = await cache.match(cacheKey);
    if (cached) {
      const hit = new Response(cached.body, cached);
      Object.entries(corsHeaders(allowedOrigin)).forEach(([k, v]) => hit.headers.set(k, v));
      hit.headers.set("X-Proxy-Cache", "HIT");
      return hit;
    }
    let upstream;
    try {
      upstream = await fetch(targetUrl.toString(), {
        method: "GET",
        headers: { Accept: request.headers.get("Accept") ?? "*/*" },
        signal: AbortSignal.timeout(TIMEOUT_MS),
      });
    } catch { return deny(504, "upstream_timeout_or_error", allowedOrigin); }
    if (!upstream.ok) return deny(502, `upstream_status_${upstream.status}`, allowedOrigin);
    const declared = Number(upstream.headers.get("Content-Length") ?? "0");
    if (declared > MAX_BYTES) return deny(413, "response_too_large", allowedOrigin);
    const body = await limitBody(upstream.body, MAX_BYTES);
    if (body === null) return deny(413, "response_too_large", allowedOrigin);
    const response = new Response(body, {
      status: 200,
      headers: {
        "Content-Type": upstream.headers.get("Content-Type") ?? "application/octet-stream",
        "Cache-Control": `public, max-age=${CACHE_TTL_SECONDS}`,
        ...corsHeaders(allowedOrigin),
        "X-Proxy-Cache": "MISS",
      },
    });
    ctx.waitUntil(cache.put(cacheKey, response.clone()));
    return response;
  },
};
async function limitBody(stream, maxBytes) {
  if (!stream) return new Uint8Array();
  const reader = stream.getReader();
  const chunks = [];
  let total = 0;
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    total += value.byteLength;
    if (total > maxBytes) { await reader.cancel(); return null; }
    chunks.push(value);
  }
  const out = new Uint8Array(total);
  let offset = 0;
  for (const c of chunks) { out.set(c, offset); offset += c.byteLength; }
  return out;
}
```
{% endraw %}

The rate limiter is a native binding, not a KV counter. Configure it in `wrangler.jsonc`, where the period [must be either 10 or 60](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/) seconds:

{% raw %}
```json
{
  "ratelimits": [
    { "name": "RATE_LIMITER", "namespace_id": "1001", "simple": { "limit": 100, "period": 60 } }
  ]
}
```
{% endraw %}

Do not build that counter on Workers KV. As of 15 July 2026 the [KV free tier](https://developers.cloudflare.com/kv/platform/pricing/) allows 1,000 writes per day. One write per request exhausts your quota in minutes.

Be honest about what the limiter does, though: Cloudflare's own docs say rate limits "are local to the Cloudflare location that your Worker runs in" and that the API is "permissive, eventually consistent, and intentionally designed to not be used as an accurate accounting system." It is a cost-control speed bump, not a hard global cap. The docs also do not state whether the binding is available on the free plan, which is why the code guards with `if (env.RATE_LIMITER)` and degrades safely.

One more trap: cache theatre. The [Cache API docs](https://developers.cloudflare.com/workers/runtime-apis/cache/) say "Workers deployed to custom domains have access to functional cache operations" and that dashboard-editor and Playground operations "will have no impact." Meanwhile [Workers Caching](https://developers.cloudflare.com/workers/cache/) is a separate, newer mechanism driven by ordinary `Cache-Control` headers that explicitly does run on workers.dev and collapses concurrent requests for the same key, which the Cache API does not.

## The line that matters more than the code

The allow-list is not a disclaimer. It is the control.

An open CORS proxy, meaning `Access-Control-Allow-Origin: *` plus `fetch(anything)`, will be found and used as an attack relay, and it will get your account terminated. The CORS header is not what prevents that; the **target** allow-list is. And it has to be exact-match membership, because `"api.example.com.attacker.test".endsWith("example.com")` evaluates to `true`. My test suite confirms the exact-match version returns 403 for that host. A suffix check silently reopens the relay you thought you closed.

The rest is the same ethic. Respect robots.txt, which is not folklore: it is [RFC 9309](https://www.rfc-editor.org/rfc/rfc9309.html), Standards Track, September 2022, and it specifies that crawlers "SHOULD NOT use the cached version for more than 24 hours." Respect the terms and the rate limits. jsDelivr's data API README says it plainly: "The API is free to use and imposes no rate limits. However, if you plan to make 100+ RPM for longer periods of time, you should contact us first." If a site blocks you, use its API, ask for access, or stop. There is nothing here about evading bot detection or defeating access controls, and the service being profiled draws the same line: its AUP bans "Trying to bypass our limits or restrictions in any way."

## Where to run it, as of mid-2026

Both numbers below were fetched on 15 July 2026. [Cloudflare's pricing docs](https://developers.cloudflare.com/workers/platform/pricing/) were last updated 7 July 2026.

| | Cloudflare Workers | Deno Deploy |
|---|---|---|
| Free requests | 100,000/day, resets 00:00 UTC | 1,000,000/month |
| Free compute | 10 ms CPU per invocation | 15 hours CPU/month + 350 GB-h memory |
| Free bandwidth | not separately metered | 20 GB egress/month |
| Free storage | KV: 1 GB, 100k reads/day, **1,000 writes/day** | 1 GiB volume + 1 GiB KV |
| Other free limits | 50 subrequests/request, 3 MB script, 128 MB memory | 20 active deployments, 50 custom domains |
| Paid entry | $5/month: 10M requests then $0.30/M, 30M CPU-ms then $0.02/M, no daily cap, 5 min CPU, 10,000 subrequests | $20/month Pro: 5M requests ($2/M over), 200 GB ($0.50/GB over) |

Two timing notes. [Deno Deploy Classic shuts down on 20 July 2026](https://docs.deno.com/deploy/classic/), five days after I pulled these numbers. Nothing migrates automatically, KV databases require contacting support, and `deployctl` is retired in favour of the built-in `deno deploy` subcommand. And current [Deno Deploy](https://docs.deno.com/deploy/) runs in two regions, US and Europe, down from six on Classic, which is a real Asia-Pacific latency regression. Re-check [the pricing page](https://deno.com/deploy/pricing) before you commit; it is moving this week.

## The takeaway

The leaderboard is worth reading precisely because it does not answer the question people ask of it. It tells you what is large, popular, unbundled, and served from this one CDN: fonts, video players, filter lists, ad-tech auction files, AI runtimes, and a quantity of raw MP4 that the platform's own terms prohibit. It is not a census of the web's dependencies, and any post that presents it as one has skipped the check that matters: React is #535.

So use it for what it is good for. Pin your versions, because the cache is better and the supply chain is safer. Put your own allow-listed, rate-limited, cached proxy in front of anything you fetch on a schedule. And when you go looking for "what the web runs on", go to a source that measures the thing you actually mean.

## Related reading

- [The Cloudflare Developer Platform, Explained Like You're Going to Ship on It](/blog/cloudflare-developer-platform/): the fuller tour of the platform the Worker above runs on.
- [How to Verify an Auditor's Findings Without Trusting the Tool: Ethical Scraping for Small Operators](/blog/blog-ethical-scraping-self-auditing/): the same robots.txt and terms-of-service discipline, applied to auditing.
- [Serving a Browser LLM Is Easy. Securing It Is the Part the Demos Skip.](/blog/securing-browser-llms-on-your-website/): loading third-party code into your page, and what that costs you.
- [The Six Security Headers Every Site Should Ship in 2026](/blog/blog-modern-security-headers/): where the CSP block above fits in the bigger header story.
- [Going Frameworkless on Cloudflare, and Why You Still Reach for Vercel, Netlify, and Square](/blog/blog-cloudflare-frameworkless-vendor-lockin/): the no-build-step position that `+esm` serves.

## Fact-check notes and sources

* **All rankings**: jsDelivr stats API, fetched 15 July 2026 for the fixed period `2026-06` ([npm by bandwidth](https://data.jsdelivr.com/v1/stats/packages?period=2026-06&type=npm&by=bandwidth&limit=20), [GitHub by bandwidth](https://data.jsdelivr.com/v1/stats/packages?period=2026-06&type=gh&by=bandwidth&limit=20), [GitHub by hits](https://data.jsdelivr.com/v1/stats/packages?period=2026-06&type=gh&by=hits&limit=20)). TB = 10^12 bytes.
* **Network totals for June 2026**: 346,742,743,884 requests, 19,372,012,771,308,052 bytes, Fastly 55.2% / Cloudflare 44.8% of bandwidth, bandwidth down 13.2% month over month while hits rose 1.7% ([network stats](https://data.jsdelivr.com/v1/stats/network?period=2026-06), [content split](https://data.jsdelivr.com/v1/stats/network/content?period=2026-06)).
* **The API defaults to hits, and ranks are zero-indexed**: verified against the [OpenAPI spec](https://data.jsdelivr.com/v1/spec.yaml) and by comparing ordered lists to [per-package output](https://data.jsdelivr.com/v1/stats/packages/npm/bootstrap?period=2026-06).
* **Pretendard**: SIL Open Font License, nine weights plus variable, 3,474 stars, users include Naver Webtoon, Kakao Bank, Wanted, Musinsa, Class101, Inflearn and Adobe Fonts ([repository](https://github.com/orioncactus/pretendard), [LICENSE](https://raw.githubusercontent.com/orioncactus/pretendard/main/LICENSE)).
* **Acceptable Use Policy quotes**, including the games-and-assets carve-out and the ban on bypassing limits: [jsDelivr Terms of Use](https://raw.githubusercontent.com/jsdelivr/jsdelivr/master/Terms%20of%20Use.md), effective 30 May 2026. jsDelivr is operated by Volentio JSD Limited, registered in England and Wales, company number [14984373](https://find-and-update.company-information.service.gov.uk/company/14984373).
* **Three deleted repos**: Lexusbro/dummy, shuvoads24-eng/azree1 and azree2 all returned HTTP 404 from the [GitHub REST API](https://api.github.com/repos/shuvoads24-eng/azree2) on 15 July 2026, as did the shuvoads24-eng account. No payload analysis was performed on the hashed-JS repositories; no claim of malice is made or implied.
* **SRI and cache behaviour**: measured response headers and SHA-384 hashes computed over raw bytes on 15 July 2026, cross-checked against [Bootstrap's published integrity values](https://getbootstrap.com/docs/5.3/getting-started/introduction/). The dynamic-file caveat is jsDelivr's own ([using SRI with dynamic files](https://www.jsdelivr.com/using-sri-with-dynamic-files)).
* **polyfill.io**: [Cloudflare's 29 February 2024 warning](https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk/) and [Sansec's 25 June 2024 research](https://sansec.io/research/polyfill-supply-chain-attack). The incident was assigned CVE-2024-38526; vendor reporting states 380,000+ hosts still embedded the script as of 2 July 2024 ([Censys](https://censys.com/blog/july-2-polyfill-io-supply-chain-attack-digging-into-the-web-of-compromised-domains/)), attributed as reporting rather than primary confirmation.
* **Pricing and limits, all fetched 15 July 2026**: [Cloudflare Workers pricing](https://developers.cloudflare.com/workers/platform/pricing/), [Workers limits](https://developers.cloudflare.com/workers/platform/limits/), [Workers KV pricing](https://developers.cloudflare.com/kv/platform/pricing/), [rate limiting binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/), [Cache API](https://developers.cloudflare.com/workers/runtime-apis/cache/), [Workers Caching](https://developers.cloudflare.com/workers/cache/), [Deno Deploy pricing](https://deno.com/deploy/pricing), [Deno Deploy docs](https://docs.deno.com/deploy/), [Deploy Classic shutdown](https://docs.deno.com/deploy/classic/).
* **robots.txt is a Standards Track RFC**: [RFC 9309](https://www.rfc-editor.org/rfc/rfc9309.html), September 2022.
* **The Worker code** was validated with `node --check` and a 16-case executed test suite under Node 24.15.0 using stubbed globals. It was not deployed to Cloudflare or run under workerd, so runtime-specific behaviour is unverified in situ.

---

*This post is informational, not engineering or security advice. Mentions of jsDelivr, Cloudflare, Deno, GitHub, and other third parties are nominative fair use, and no affiliation is implied. Rankings reflect a single fixed period (June 2026) fetched on 15 July 2026; pricing, free tiers, and platform limits are current as of mid-2026 and change quickly. Verify against the live sources before you build.*


---

Canonical HTML: https://jwatte.com/blog/jsdelivr-top-packages-edge-proxy-builds/
RSS: https://jwatte.com/feed.xml
JSON Feed: https://jwatte.com/feed.json
Hero image: https://jwatte.com/images/jsdelivr-top-packages-edge-proxy-builds.webp
