{"id":51446128,"url":"https://github.com/sharoon7171/doodstream-direct-resolver","last_synced_at":"2026-07-05T16:01:28.523Z","repository":{"id":368305686,"uuid":"1284522097","full_name":"sharoon7171/doodstream-direct-resolver","owner":"sharoon7171","description":"Zero-dependency Node.js service that resolves DoodStream embed URLs to direct CDN links. Replays the pass_md5 player handshake, builds tokenized URLs, and verifies with ranged CDN requests. Native HTTP/2 client with Chrome TLS fingerprint for mirror access; Referer-aware byte proxy for browser playback.","archived":false,"fork":false,"pushed_at":"2026-06-30T00:35:27.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T02:20:38.874Z","etag":null,"topics":["doodstream","embed-player","http2","native-node","nodejs","reverse-engineering","stream-proxy","stream-resolver","tls-fingerprinting","zero-dependencies"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sharoon7171.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-30T00:30:47.000Z","updated_at":"2026-06-30T00:38:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sharoon7171/doodstream-direct-resolver","commit_stats":null,"previous_names":["sharoon7171/doodstream-direct-resolver"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sharoon7171/doodstream-direct-resolver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharoon7171%2Fdoodstream-direct-resolver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharoon7171%2Fdoodstream-direct-resolver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharoon7171%2Fdoodstream-direct-resolver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharoon7171%2Fdoodstream-direct-resolver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sharoon7171","download_url":"https://codeload.github.com/sharoon7171/doodstream-direct-resolver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharoon7171%2Fdoodstream-direct-resolver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35160046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["doodstream","embed-player","http2","native-node","nodejs","reverse-engineering","stream-proxy","stream-resolver","tls-fingerprinting","zero-dependencies"],"created_at":"2026-07-05T16:01:26.894Z","updated_at":"2026-07-05T16:01:28.503Z","avatar_url":"https://github.com/sharoon7171.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DoodStream Direct Link Resolver\n\nZero-dependency Node.js service that resolves a DoodStream **video ID** to a direct CDN MP4 link. The implementation reverse-engineers the embed player handshake and replays it with a native Chrome-fingerprint HTTP client — no npm dependencies, no headless browser, no captcha automation.\n\n## Stack\n\n| Layer | Technology |\n| --- | --- |\n| Runtime | Node.js (ES modules) |\n| HTTP server | `node:http` |\n| Upstream client | `node:http2`, `node:https`, `node:tls`, `node:zlib` |\n| Frontend | Static HTML/CSS/ES module (served by the same process) |\n\n```bash\nnpm start          # node src/server/index.js\nPORT=8787 npm start\n```\n\nDefault listen address: `http://localhost:8787`\n\n## Architecture\n\n```mermaid\nflowchart TB\n  subgraph client [Browser / API consumer]\n    UI[public/app.js]\n    API[POST /api/resolve]\n    Proxy[GET/HEAD /api/stream]\n  end\n\n  subgraph server [src/server/]\n    Index[index.js]\n    ResolveRoute[routes/resolve.js]\n    StreamRoute[routes/stream.js]\n    Resolver[doodstream/resolver.js]\n    HttpClient[http/client.js]\n    Headers[http/browser-headers.js]\n    HttpResp[lib/http-response.js]\n  end\n\n  subgraph shared [src/lib/]\n    ParseId[parse-video-id.js]\n  end\n\n  subgraph external [External]\n    Bootstrap[doodstream.com]\n    Mirror[Active mirror / Cloudflare]\n    CDN[CDN origin]\n  end\n\n  UI --\u003e ParseId\n  UI --\u003e API\n  UI --\u003e Proxy\n  API --\u003e Index\n  Proxy --\u003e Index\n  Index --\u003e ResolveRoute\n  Index --\u003e StreamRoute\n  ResolveRoute --\u003e ParseId\n  ResolveRoute --\u003e Resolver\n  StreamRoute --\u003e HttpClient\n  Resolver --\u003e HttpClient\n  HttpClient --\u003e Headers\n  ResolveRoute --\u003e HttpResp\n  StreamRoute --\u003e HttpResp\n  HttpClient --\u003e Bootstrap\n  Bootstrap --\u003e Mirror\n  HttpClient --\u003e Mirror\n  HttpClient --\u003e CDN\n  Proxy --\u003e CDN\n```\n\n### Module map\n\n```\n/\n├── public/\n│   ├── index.html                Dev/test UI shell\n│   ├── app.js                    Resolve client, live timers, copy links, proxy playback\n│   └── app.css\n└── src/\n    ├── lib/\n    │   └── parse-video-id.js     Video ID validation (shared by server + browser)\n    └── server/\n        ├── index.js              Entry point: API routing + static file server\n        ├── lib/\n        │   └── http-response.js  readJsonBody, sendJson\n        ├── routes/\n        │   ├── resolve.js        POST /api/resolve orchestration\n        │   └── stream.js         GET/HEAD /api/stream byte proxy\n        ├── doodstream/\n        │   └── resolver.js       Bootstrap, embed decode, pass_md5, direct link build\n        └── http/\n            ├── client.js         Chrome TLS + HTTP/2 client (fetchText, fetchStream)\n            └── browser-headers.js document vs fetch header profiles\n```\n\n### Responsibilities\n\n| Module | Role |\n| --- | --- |\n| `parse-video-id.js` | Single parser shared by server route and browser client for consistent validation |\n| `src/server/index.js` | Routes `POST /api/resolve`, `GET/HEAD /api/stream`, serves `public/` and `src/lib/` at `/lib/*` |\n| `routes/resolve.js` | Parses `videoId`, calls resolver, verifies link, returns JSON |\n| `routes/stream.js` | Proxies CDN range requests with injected `Referer`; supports `HEAD` for external players |\n| `doodstream/resolver.js` | Implements the DoodStream embed → CDN URL protocol |\n| `http/client.js` | All upstream HTTPS; session pooling; H2 primary, H1 fallback |\n| `http/browser-headers.js` | Chrome 131 UA + `sec-*` headers for document and XHR-like modes |\n| `public/app.js` | Integration reference for the two API endpoints |\n\n## Resolve pipeline\n\nDoodStream serves plain `video/mp4` on the CDN. Access control is at **URL discovery** and **CDN Referer checks**, not stream encryption.\n\n```mermaid\nsequenceDiagram\n  participant R as routes/resolve.js\n  participant V as doodstream/resolver.js\n  participant H as http/client.js\n  participant B as doodstream.com\n  participant M as Active mirror\n  participant C as CDN\n\n  R-\u003e\u003eV: resolveDirectLink(videoId)\n  V-\u003e\u003eH: fetchText GET doodstream.com/e/{id} (document mode)\n  H-\u003e\u003eB: Chrome TLS + H2\n  B--\u003e\u003eM: redirect\n  M--\u003e\u003eH: embed HTML\n  V-\u003e\u003eV: decodeEmbedPage(html)\n  Note over V: passMd5Path, playbackToken\n  V-\u003e\u003eH: fetchText GET /pass_md5/... (fetch mode, Referer)\n  H-\u003e\u003eM: Chrome TLS + H2\n  M--\u003e\u003eH: plaintext CDN prefix\n  V-\u003e\u003eV: buildDirectLink(prefix, token)\n  R-\u003e\u003eV: verifyDirectLink(directLink, referer)\n  V-\u003e\u003eH: fetchText Range bytes=0-15 (fetch mode, Referer)\n  H-\u003e\u003eC: Chrome TLS + H2\n  C--\u003e\u003eH: 206 Partial Content\n  R--\u003e\u003eR: JSON response\n```\n\n### Step-by-step (resolver.js)\n\n1. **`GET https://doodstream.com/e/{videoId}`** — document headers; follows redirects to the active mirror; canonical origin taken from the final URL.\n2. **`decodeEmbedPage(html)`** — regex extraction of:\n   - `/pass_md5/{hash}/{token}` path (inline `$.get`, quoted string, or bare path)\n   - playback token from `makePlay()` query string or pass_md5 path segment\n3. **`GET {origin}{passMd5Path}`** — fetch headers; `Referer: {origin}/e/{videoId}`.\n4. **`decodePassMd5Response(body)`** — body is either:\n   - plaintext `https://...` CDN prefix\n   - `RELOAD` → session expired\n   - non-URL text → rate limit / token reuse\n5. **`buildDirectLink(cdnPrefix, token)`** — mirrors site player: 10 random `[A-Za-z0-9]` + `?token={token}\u0026expiry={Date.now()}`.\n6. **`verifyDirectLink`** — `Range: bytes=0-15` against CDN with `Referer: {origin}/`; requires HTTP 200 or 206; reads total size from `Content-Range`.\n\nNo WASM, no secondary decrypt pass on media bytes.\n\n### Mirror discovery\n\nNo mirror URL or environment variable is required. `doodstream.com/e/{videoId}` redirects to whichever mirror currently hosts the embed (for example `playmogo.com`). The resolver uses the redirected origin for `pass_md5` and sets `referer` to `{origin}/`.\n\n## HTTP client and Cloudflare\n\nMirror hosts reject default Node/curl TLS fingerprints with **403**. `http/client.js` impersonates Chrome at the transport layer:\n\n| Mechanism | Implementation |\n| --- | --- |\n| TLS ciphers | Chrome cipher suite order via `tls.connect` |\n| TLS extensions | `SSL_OP_TLSEXT_PADDING`, `SSL_OP_NO_ENCRYPT_THEN_MAC`, X25519/P-256 curves |\n| ALPN | `h2`, `http/1.1` |\n| HTTP/2 | Chrome SETTINGS (window 6291456, max streams 1000, etc.) |\n| Sessions | Per-origin H2 session cache in `sessions` Map |\n| Fallback | H2 failure → H1 with same TLS profile |\n| Headers | `documentHeaders()` for page loads; `fetchHeaders()` for API/CDN |\n| Compression | br/gzip on buffered text (`fetchText`); br/gzip/deflate on streams (`fetchStream`) |\n\n`fetchText(url, extraHeaders, mode)` — buffered response for HTML and pass_md5; follows redirects.  \n`fetchStream(url, extraHeaders)` — streaming response for CDN proxy; forwards `Range`.\n\n## Stream proxy\n\nThe CDN enforces **`Referer: {mirror-origin}/`**. Browsers cannot set a cross-origin Referer on `\u003cvideo src\u003e`, so in-page playback uses a local relay:\n\n```\nGET /api/stream?url={encodeURIComponent(directLink)}\u0026referer={encodeURIComponent(referer)}\nHEAD /api/stream?url=...\u0026referer=...\n```\n\n`routes/stream.js` forwards the client's `Range` header on `GET`, fetches upstream via `fetchStream`, and pipes bytes back with `Content-Range` / `Content-Length` preserved. `HEAD` probes upstream with `Range: bytes=0-0` and returns video headers without a body.\n\nDirect CDN access (outside the browser) only requires attaching the `referer` field from the resolve response.\n\n## API contract\n\n### `POST /api/resolve`\n\nRequest:\n\n```http\nPOST /api/resolve\nContent-Type: application/json\n\n{\"videoId\": \"5x50byl1sld3\"}\n```\n\nSuccess `200`:\n\n```json\n{\n  \"videoId\": \"5x50byl1sld3\",\n  \"title\": \"string | null\",\n  \"directLink\": \"https://cdn.../....mp4?token=...\u0026expiry=...\",\n  \"referer\": \"https://playmogo.com/\",\n  \"contentLength\": \"399715618\"\n}\n```\n\nErrors:\n\n| Status | Cause |\n| --- | --- |\n| `400` | Invalid video ID, missing embed data, pass_md5 failure, verification error |\n| `502` | CDN verification returned non-200/206 |\n\n### `GET /api/stream` and `HEAD /api/stream`\n\nQuery params: `url` (direct CDN link), `referer` (from resolve response).\n\n`GET` forwards `Range` from the client. `HEAD` returns upstream video headers (no body) for player probes. `502` on upstream failure.\n\n## Frontend integration (public/app.js)\n\nReference flow for consumers building on the API:\n\n1. Validate with `parseVideoId` from `/lib/parse-video-id.js`\n2. `POST /api/resolve` with `{ videoId }` → receive `directLink`, `referer`, `contentLength`\n3. **Direct use:** pass `directLink` + `Referer: referer` to any HTTP client\n4. **Browser playback:** set `\u003cvideo src\u003e` to `/api/stream?url=...\u0026referer=...` (same-origin proxy)\n\nThe bundled UI shows live resolve and playback-start timers while work is in progress.\n\n## Development notes\n\n- **Zero deps:** no `package-lock.json`; nothing to install beyond Node.\n- **Token single-use:** pass_md5 tokens and direct links can fail on retry; resolve fresh per attempt.\n- **Video ID only:** input is the alphanumeric file code (for example `5x50byl1sld3`), not a full mirror URL.\n- **Static serving:** `src/server/index.js` exposes `public/` at root paths and `src/lib/` at `/lib/*` for shared browser modules.\n\n## Disclaimer\n\nThis repository is provided for **educational and research purposes** only, to document embed-player URL resolution, TLS client fingerprinting, and CDN access patterns. You are responsible for compliance with applicable laws, site terms of service, and copyright in your jurisdiction. Do not use this code to access, redistribute, or monetize content without authorization. The authors assume no liability for misuse.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharoon7171%2Fdoodstream-direct-resolver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsharoon7171%2Fdoodstream-direct-resolver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharoon7171%2Fdoodstream-direct-resolver/lists"}