QuickWatch Docs
Quickwatch API & Scrapers
QuickWatch's Skip API, and our streaming scrapers, download scrapers and music proxying. Curated JavaScript snippets to help you build your own streaming app.
Skips API
Public GET route that returns skip timestamps for TV episodes.
Example request (public, CORS open)
const res = await fetch('https://quickwatch.co/api/skips?title=&season=&episode=&runtime=');const data = await res.json();
Example response
{"found": true,"skip_times": {"intro": {"start": null,"end": null},"recap": {"start": null,"end": null},"credits": {"start": 2657000,"end": null},"ending": {"start": null,"end": null},"up_next": {"start": null,"end": null}}}
Response shape: { found: boolean, skip_times: object | null }. If no match is found, you receive { found: false, reason: string }.
Streaming Scrapers
I wrote these streaming scrapers to fetch sources around the internet. When fetching sources, we aim to find a hls playlist or a video url, along with some headers.
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36';async function resolveVideasy({ title, year, tmdbId, mediaType = 'movie', server = 'myflixerzupcloud' }) {const qs = new URLSearchParams({ title, year: String(year), tmdbId: String(tmdbId) });if (mediaType === 'tv') qs.set('mediaType', 'tv');const apiUrl = `https://api.videasy.net/${server}/sources-with-title?${qs}`;const encrypted = await fetch(apiUrl, { headers: { 'User-Agent': UA } }).then((r) => r.text());const decrypted = await fetch('https://enc-dec.app/api/dec-videasy', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ text: encrypted, id: String(tmdbId) }),}).then((r) => r.json());const stream = (decrypted.sources || [])[0];return { url: stream.url, headers: { origin: 'https://videasy.net', referer: 'https://videasy.net/' }, type: 'hls' };}
Downloading Scrapers
I also wrote these downloaders to get direct download links for movies/shows on the Download section of movie/tv pages. These usually dont need headers.
async function get111477Downloads({ mediaItem, mediaType = 'movie' }) {const q = mediaItem?.title || mediaItem?.name;const url = mediaType === 'tv' ? 'https://a.111477.xyz/tvs/' : 'https://a.111477.xyz/movies/';const html = await fetch('/api/proxy', { method: 'POST', body: JSON.stringify({ url }) }).then(r => r.text());if (!html) return [];const row = Array.from(new DOMParser().parseFromString(html, 'text/html').querySelectorAll('tr[data-name]')).find(r => r.getAttribute('data-name')?.toLowerCase().includes(q.toLowerCase()));if (!row) return [];let dUrl = row.getAttribute('data-url');if (dUrl.startsWith('/')) dUrl = `https://a.111477.xyz${dUrl}`;const dHtml = await fetch('/api/proxy', { method: 'POST', body: JSON.stringify({ url: dUrl }) }).then(r => r.text());return Array.from(new DOMParser().parseFromString(dHtml, 'text/html').querySelectorAll('a[class*="maxbutton"]')).map(n => ({ url: n.getAttribute('href'), type: 'download' }));}
The music API (/api/music/[...path]) forwards requests to several Tidal backends with random selection and caching. All responses are CORS-enabled.
Typical paths: /api/music/v1/tracks/:id, /api/music/v1/albums/:id, /api/music/v1/playlists/:id
async function fetchTrack(trackId) {const res = await fetch(`/api/music/v1/tracks/${trackId}?countryCode=US`, {headers: { Accept: 'application/json' },});if (!res.ok) throw new Error('music lookup failed');return res.json();}