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

@volter/twin-youtube

v0.1.35

Published

Local YouTube Data API v3 twin (resumable uploads, media served with Range) with a youtube.com mirror, built on @volter/world-core.

Downloads

2,376

Readme

@volter/twin-youtube

A local, stateful, vendor-faithful twin of the YouTube Data API v3 (https://www.googleapis.com/youtube/v3/*), built on the shared @volter/world-core kernel.

Point an unmodified client at it — Google's own generated @googleapis/youtube, or plain fetch — and get vendor-correct responses offline: the real list envelope, real part selection, string-typed statistics, the real Google error envelope, a modeled daily quota that actually runs out, and videos.insert through the real resumable upload protocol, with the uploaded bytes kept and served back with HTTP Range. A youtube.com mirror shows the channel and its videos as a creator sees them.

bun packages/twin/youtube/src/cli.ts serve --port 12180
# then, from your app:
YOUTUBE_TWIN_URL=http://127.0.0.1:12180 node --require @volter/world-core/inject app.js

# youtube.com over the same state: sign in, channel page, watch page, upload
bun packages/twin/youtube/src/cli.ts mirror --port 12181

Coverage

Partial and honest. The manifest (src/youtube-capabilities.ts) is the real vendor surface as the denominator — enumerated top-down from the vendor's own reference nav, every resource × every published method — so coverage reads well under 100% and growing the denominator later will lower it further. That is success, not regression.

The manifest declares 101 done of 209 capabilities; the gate's recorded baseline (census.json) is the floor it may not fall below.

What is modeled

| Area | State | |---|---| | channels.list | id / forHandle / forUsername filters; snippet, statistics, contentDetails, status, topicDetails, brandingSettings parts | | videos.list | id filter + chart=mostPopular ordering over real state; snippet, contentDetails, statistics, status, player parts | | search.list | q, type, channelId, order, publishedAfter/Before, pagination, the youtube#searchResult id shape | | playlists | list / insert / update / delete (the OAuth write surface); update and delete of another channel's playlist are 403 playlistForbidden | | playlistItems | list / insert / delete, with dense 0..n-1 positions maintained across both (in another channel's playlist, 403 playlistItemsNotAccessible); a channel's UU… uploads playlist lists its videos newest first | | videos.insert | uploadType=resumable (a random session id in Location; chunked PUT with Content-Range on the session URI, which is its own credential (no bearer needed); every chunk but the last must be a multiple of 256 KiB, and the twin keeps such a chunk in whole 256 KiB units (its own rule; Google documents only the multiple); 308 Resume Incomplete with Range; bytes held plus a body past X-Upload-Content-Length refused, with or without Content-Range; 201 with the video; 404 for an unknown session or one past the twin's one-week lifetime), uploadType=multipart and uploadType=media; metadata validated at the first request (invalidTitle, invalidDescription, invalidCategoryId, mediaBodyRequired); charged to the upload bucket. A new video reads uploadStatus: uploaded; processing (duration and definition read from the MP4's own headers) lands on a later read, by World time | | thumbnails.set | uploadType=media or multipart; only the video's channel may set it (403 forbidden); a video.thumbnail entry that performs as thumbnails.set on its own (on an uploaded, published or pulled video); the image stored and served at the URLs the response names (invalidImage, mediaBodyRequired, videoNotFound) | | media | the uploaded bytes at <base>/videoplayback?v=<id> with Range (206 / 416, an open-ended range capped at 8 MiB, a whole GET streamed, HEAD from the size) and custom thumbnails at <base>/vi/<id>/<size>.jpg, under the twin's public base, read at the branch or its ancestors; a private video plays only for its channel's token (access_token=), else 403; an unlisted one plays for anyone with the link | | reference data | videoCategories, i18nLanguages, i18nRegions, videoAbuseReportReasons | | auth | API key as ?key= and as X-Goog-Api-Key; writes require an OAuth bearer token registered through /_twin/tokens (kept in the log as its SHA-256 — unsalted: the kernel offers no per-World secret to key an HMAC with): it is its channel for channels.list?mine=true and for every write it carries, and a bearer never registered is Google's 401 authError on mine and on every write | | quota | all three documented daily buckets, with the vendor's own per-method unit costs | | errors | the real Google envelope — unknownPart, missingRequiredParameter, incompatibleParameters, invalidFilters, invalidPageToken, quotaExceeded, rateLimitExceeded, playlistNotFound, videoNotFound, and 403 on owner-only parts | | connector | pull channels + videos over an injected client, idempotent, chunked at 50 ids/call; a World's uploaded video performs on the real root as a resumable upload of its bytes (with its custom thumbnail), charged to the pack's rate budget | | mirror | youtube.com: sign-in, the channel page, the watch page with the player, the upload dialog |

Everything else the vendor publishes — subscriptions, comments/commentThreads, captions, channelSections, activities, watermarks, members and the whole Live Streaming family — is a filed todo in the manifest, and an unmodeled route 404s like the vendor rather than faking a success.

Wire facts this twin gets right (and most mocks get wrong)

  • statistics counts are STRINGS. viewCount, subscriberCount, videoCount, likeCount, commentCount — all strings on the wire. So is contentDetails.caption ("true" / "false").
  • An unknown id on a list endpoint is 200 with items: [], never a 404.
  • part selects the response. Ask for snippet and you do not get statistics.
  • Multi-value parameters arrive in two forms. ?part=a,b (what a hand-built client sends) and ?part=a&part=b (what Google's generated SDK sends). Both are accepted; supporting only the first silently drops every value after the first.
  • Owner-only parts 403. fileDetails / processingDetails / suggestions on videos.list, auditDetails / contentOwnerDetails on channels.list.
  • Reads take an API key; writes take OAuth. A write with only a key is 401 Login Required.

Quota

The twin models the vendor's current three-bucket quota, not the widely-repeated legacy one: 100 search.list calls, 100 videos.insert calls, and 10,000 units/day for everything else, with reads at 1 unit and writes at 50 (getting-started §Quota usage, determine_quota_cost). The often-cited search.list = 100 units and videos.insert = 1600 units figures are stale.

Exhausting a bucket returns the real 403 quotaExceeded (domain youtube.quota) — and returns it instead of serving the call. Arm it in a test through the twin-only route:

curl -XPOST localhost:12180/youtube/v3/_twin/quota -d '{"unitsAllowance":2}'

Seeding (twin-only routes)

YouTube exposes no API route that creates a channel, and no OAuth consent a World can run for every test. So channels, metadata-only videos and access tokens are seeded through twin-only routes that sit outside the vendor's surface and that a real client never calls — deliberately absent from the manifest, because counting scaffolding as coverage would be padding:

  • POST /youtube/v3/_twin/channels
  • POST /youtube/v3/_twin/videos (a video with metadata and no media)
  • POST /youtube/v3/_twin/tokens — { "token", "channelId" }: a bearer that signs in as the channel
  • POST /youtube/v3/_twin/quota · GET /youtube/v3/_twin/quota

A video with media, playlists and playlist items are not seeded this way: they have a real vendor write path (videos.insert, playlists.insert, playlistItems.insert), so they are created through it. Resumable sessions and their staged bytes live in the service's byte annex, not in the event log; only the finished upload is a video.create action.

Fidelity

src/youtube-sdk.integration.test.ts drives Google's own generated client, @googleapis/youtube@^34, unmodified at the twin. The only thing configured is the SDK's own public rootUrl option — configuration, not modification. That test earned its place immediately: it caught the repeated-key parameter form described above, which a hand-written fetch test could not have surfaced.

The mirror

world-youtube mirror serves youtube.com over the twin's state on one origin, and a served World mounts the same shell at <vendor>/mirror/. A creator uploads a video and reads their channel in the browser, so the rule in Adding a twin — "when someone does this vendor's core job, do they open a browser or write code?" — asks for one.

  • Sign-in is Google's two steps: the channel's @handle, then the bearer registered through /_twin/tokens in place of a password, checked by channels.list?mine=true. Both stay in the tab's sessionStorage.
  • The channel page reads channels.list?forHandle=, then the channel's UU… uploads playlist and videos.list: banner, avatar, name, @handle, subscriber and video counts (the channel's statistics), and the Videos tab's grid (Latest / Popular / Oldest) with duration badges. A thumbnail is the custom one set through thumbnails.set, else a frame of the video's own bytes.
  • The watch page plays videoplayback?v=<id> in an HTML5 <video> under youtube.com's player chrome (seeking is a Range read; the signed-in token rides the URL as access_token, so a private video plays for its own channel), with the title, the channel row, the description box and the channel's other uploads beside it.
  • Upload (Create) is the resumable videos.insert from the browser: select a file, set title, description and visibility, publish, and land on the video's watch page.

The twin serves no channel art, so the banner and avatar are drawn from the channel's id and title.

Rate budget

Live calls go through one guarded choke point, liveYouTubeExecute, with a persistent fail-closed ledger (src/youtube-budget.ts). YouTube's published scheme is already a weighted unit budget, so the declaration reproduces the vendor's own numbers — a read costs 1, a write costs 50 — rather than inventing weights. See that file's header for how the daily allowance becomes an hourly ceiling (400 units/hour ⇒ 9,600/day, under the real 10,000) and why the 60-unit/60s burst sub-ceiling is what it is.

Raw calls to www.googleapis.com outside that factory are banned, and src/youtube-budget.test.ts enforces the ban over tracked files.

Connector

pullYouTubeChannels / pullYouTubeVideos / syncYouTubeFromReal pull real metadata over an injected client (the real API in prod, a fake in every test), fold it through the kernel observation path, and are idempotent — a re-pull of identical state appends nothing.

A World's upload performs with its bytes. performYouTubeAction sends a video.create entry to the vendor through the resumable videos.insert over the credential the kernel's executor sets at a real boundary. The pack's rate budget (budgetedYouTubeExecute, one ledger per sealed credential — every World and branch performing with one Google key shares it; a twin-only perform with none sealed uses its control root's) charges the insert ONCE, at the session start, at YouTube's documented 1 quota — the session's chunk PUTs are never charged, as Google's quota counts the insert and not the bytes, so a started upload always finishes or fails on the vendor's own answer. The session URI is kept in the byte annex as soon as it opens, so a perform after a crash asks that session where it stands before opening another. The session POST carries the entry's snippet and status; the session URI's path is anchored at /upload/youtube/v3/ (the executor adds the root's origin and prefix); the bytes cross in 4 MiB PUT chunks read as ranges from the byte annex (the branch's or an ancestor's), following each 308's Range. A 5xx or a failed request is recovered by asking the session where it stands, with exponential backoff, at most five times in a row — so a final chunk whose answer was lost is never uploaded twice — and a chunk the vendor keeps none of twice in a row fails the perform. The 201's video id is the entry's external id, and the video's custom thumbnail, if the World set one, crosses with it through thumbnails.set — the latest image, which covers every thumbnail entry of that video written so far. A thumbnail set later (on an uploaded, published or pulled video) is its own video.thumbnail entry and crosses on its own perform; an entry already covered, or superseded by a later one still to perform, sends nothing, so several thumbnails make one thumbnails.set with the latest image. A thumbnail entry whose video is not at YouTube (its upload reverted or never performed, and never pulled) is refused with that reason, never sent with a local id.

The twin's own accounting — registered tokens, the quota ledger, a channel's upload count — is bookkeeping (_-typed subjects), never a deployable entry.

Privacy in listings: the uploads playlist lists a channel's private videos to every caller. Google's playlistItems reference does not say what another channel sees there, so the twin does not guess.

Playlist push is a filed gap, not a stub. Those writes require an OAuth 2.0 user credential the API-key client never mints, so youTubeRequestForAction returns null and a push is an honest no-op that issues no request (youtube.connector.push_oauth_writes, todo).

Injection

Set YOUTUBE_TWIN_URL and the injector routes YouTube traffic here. Two hosts are intercepted, and both matter:

  • youtube.googleapis.com — what Google's own generated client actually calls. Every one of @googleapis/youtube's 83 endpoint methods defaults to rootUrl || 'https://youtube.googleapis.com/'. Not shared with any other vendor, so no path test applies.
  • www.googleapis.com — the legacy alias, which also serves v3 and is what hand-built clients send (the priority consumer uses exactly this). Shared with googleauth (Google's OAuth2 token exchange), so VENDOR_HOSTS disambiguates the two by path — /youtube/v3/* and /upload/youtube/v3/* are this twin's; everything else on that host stays googleauth's.

A §9 review caught this pack originally matching only www.googleapis.com, which meant a default-configured SDK escaped the injector entirely and tunnelled to the real Google. The pack's own SDK fidelity test could not catch it, because that test sets rootUrl at the twin and so never exercises the SDK's default. This is the openai/posthog/supermemory/xai incident class: a vendor key existed, but not for the host the SDK really uses.

See the PATH-AWARE DISAMBIGUATION header in packages/world-core/inject.cjs and the assertions in scripts/vendor-hosts.test.ts, which now pin both hosts, the /upload/ prefix, and — structurally — that every post-TLS handler resolves with a path.

If your app also uses real Google auth

Set GOOGLEAUTH_TWIN_URL too, or Google auth calls will fail with a 502.

Because www.googleapis.com is shared, running the YouTube twin makes the world intercept the whole host — the decision to intercept happens at TLS-handshake time, when only the hostname is known, before any path exists. Once TLS is terminated there is no way back to a passthrough tunnel. So a world with YOUTUBE_TWIN_URL set but GOOGLEAUTH_TWIN_URL unset will answer https://www.googleapis.com/oauth2/v1/certs (which google-auth-library fetches) with:

502  no twin serves www.googleapis.com for path "/oauth2/v1/certs".

That is the honest answer rather than a wrong one — the alternative, before paths were considered at all, was routing those requests into whichever twin happened to be declared first — but it is a new constraint. The 502 body names the variable to set. Hosts this twin does not claim (youtube.googleapis.com is its own) are unaffected.