Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VidUP Stream Resolver

Turns a TMDB movie or TV episode ID into HLS .m3u8 URLs from vidup.to.

Vidup does not expose streams through a simple API — playback depends on client-side code that negotiates with their servers and decrypts the response. This project runs that same client logic in Node to produce CDN manifest URLs for every available host on a title.

How it is resolved

resolveStreamLive in src/resolve/resolver.js drives the pipeline.

flowchart TB
  subgraph paths [src/resolve/paths.js]
    IN[contentPath or type + id] --> CP["/movie/{id} or /tv/{id}/{s}/{e}"]
  end
  subgraph page [Page fetch]
    CP --> GET["GET {ORIGIN}{contentPath}"]
    GET --> EN[parsePageToken → en]
  end
  subgraph vm [src/vidup-vm]
    EN --> SB[createVidupSandbox]
    SB --> CH[sliceVidupChunk + VM_PRELUDE + VM_RUNNER]
    CH --> RS[vm.runServers]
    RS --> W[8 workers × vm.runStream]
  end
  W --> URL[streamUrl per host]
  URL --> EVT[status · found · ready · fail · done]
  GET -.-> VIDUP[(vidup.to)]
  W -.-> VIDUP
Loading

1. Build the content path

src/resolve/paths.js turns your input into the path vidup.to uses for that title.

For a movie, pass the TMDB ID — the path becomes /movie/{id}. For TV, pass ID, season, and episode — the path becomes /tv/{id}/{season}/{episode}.

You can pass { type, id, season?, episode? }, a ready-made contentPath string, or query parameters through parseStreamRequest.

2. Read the page and find the token

The resolver requests {ORIGIN}{contentPath} using the USER_AGENT from src/config/defaults.js.

Vidup embeds a short-lived token called en inside the page HTML. parsePageToken gathers the self.__next_f.push([1,"…"]) script chunks Next.js leaves on the page, joins them, unescapes the string, and pulls out "en".

If that token is missing, resolution stops with stage page-token and error en token missing.

3. Load the client VM

createVidupSandbox (src/vidup-vm/sandbox.js) loads vendor/vidup-client-chunk-294.js — the same webpack chunk the site uses — and cuts out only the pieces needed for stream logic (src/vidup-vm/chunk.js).

Those pieces are wrapped with a small browser shim (VM_PRELUDE) and two entry functions (VM_RUNNER): runServers lists hosts, runStream decodes one host. The code runs inside a fake globalThis with stubbed document, navigator, localStorage, and a custom fetch.

That fetch is important: relative URLs are resolved against vidup.to, and every outbound request carries User-Agent, Origin, and Referer pointing at the title page — the same headers the real site sends.

4. List stream hosts

vm.runServers(en) runs the site's oc function with the page token. It returns an array of hosts such as Premier, Zenith, or CineX.

Each host includes a display name, optional description, and a data field — an opaque slug the site uses in the next POST request. Nothing in data is meant to be parsed by hand.

If no hosts come back, resolution stops at stage servers.

5. Decode every host in parallel

The resolver runs eight workers against a shared queue. Each worker picks a host and calls vm.runStream(host.data):

  1. Build the POST path from the runtime string decoder inside the bundle.
  2. POST to vidup.to with the method and headers the bundle expects.
  3. Decrypt the response body and read out the final URL.

When a host succeeds, you get a streamUrl — a direct link to a .m3u8 file on a CDN. When a host fails, that host is skipped; the others keep going.

The first successful host triggers ready so playback can start while the rest are still probing. When all workers finish, done carries the full server list.

Events

resolveStreamLive reports through a callback:

Event Meaning
status A phase started — { step, text } for UI progress
found One host decoded — { name, description, streamUrl, ms }
ready First playable result — { ok, streamUrl, servers, source? }; source.title appears when the decode returns a title
fail Nothing worked or an early step broke — { ok: false, stage, error }
done All workers finished — { servers } with every host that succeeded

The streamUrl in these events is always the raw CDN address. Resolve never rewrites or proxies it.

How playback works

A streamUrl from resolve points at a third-party CDN, not at vidup.to. Those CDNs only serve data when the request looks like it came from the vidup site — specifically when Referer and Origin match vidup.to.

If your player fetches the .m3u8 and every .ts segment with those headers already set, you can use streamUrl as-is.

If not — for example a browser player that cannot set referer on segment requests — use proxyHls in src/hls/proxy.js. It fetches on your behalf with ORIGIN and USER_AGENT from src/config/defaults.js and returns the bytes.

flowchart TB
  URL[streamUrl] --> FETCH[proxyHls + vidup headers]
  FETCH --> KIND{response type}
  KIND -->|".m3u8"| REW[rewrite media lines in playlist]
  KIND -->|binary segment| STRIP[stripPngTs]
  REW --> MAN[manifest to consumer]
  STRIP --> SEG[TS to consumer]
  REW --> FETCH
Loading

Manifests — when the fetched file is an HLS playlist, proxyHls walks each line. Comment lines stay as they are. Media lines are rewritten so the player asks the proxy for the next URL instead of hitting the CDN directly. That way every nested playlist and segment inherits the same vidup headers.

Segments — for binary responses, the proxy returns the payload after stripPngTs. Some CDNs wrap MPEG-TS data inside a PNG file; this helper peels off the PNG header and leaves plain transport stream bytes.

Resolve and playback never call each other. Resolve hands off a URL; playback is entirely the consumer's choice.

Disclaimer

For educational and research purposes only. Do not use this project to violate terms of service, bypass access controls, or distribute copyrighted material. No liability for misuse.

About

Resolve vidup.to streams from TMDB IDs to upstream HLS .m3u8 URLs. Lists every host on a title and decodes each to a CDN manifest — matching the site client, runnable headless in Node.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages