{"slug": "yt2mp3-gs-scrape-by-claidex-alfidev", "title": "yt2mp3.gs scrape by claidex ( alfidev )", "summary": "A developer known as claidex (alfidev) created a script to scrape the YouTube-to-MP3 conversion service yt2mp3.gs. The script automates the authentication, conversion, and download process, handling redirects and progress polling. It demonstrates how to programmatically interact with the service's API endpoints hosted on epsilon.epsiloncloud.org.", "body_md": "| import { createWriteStream } from \"fs\"; | |\n| import { pipeline } from \"stream/promises\"; | |\n| const EPS = \"epsilon.epsiloncloud.org\"; | |\n| const ORIGIN = \"https://yt2mp3.gs\"; | |\n| const youtube = \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"; | |\n| const FORMAT = \"mp3\"; | |\n| let key, geo; | |\n| const HEADERS = { | |\n| \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:152.0) Gecko/20100101 Firefox/152.0\", | |\n| \"Accept\": \"*/*\", | |\n| \"Accept-Language\": \"en-US,en;q=0.9\", | |\n| \"Origin\": ORIGIN, | |\n| \"Referer\": `${ORIGIN}/`, | |\n| }; | |\n| async function req(url, extra = {}) { | |\n| const res = await fetch(url, { headers: { ...HEADERS, ...extra } }); | |\n| const text = await res.text(); | |\n| if (!res.ok) throw new Error(`HTTP ${res.status} ${url}`); | |\n| return JSON.parse(text); | |\n| } | |\n| async function auth(vid, fmt) { | |\n| const r = await req(`https://${EPS}/api/v1/auth?_=${Date.now()}`); | |\n| if (r.error > 0) throw new Error(`auth: ${r.error}`); | |\n| geo = r.geo; | |\n| key = r.key; | |\n| await initialize(vid, fmt); | |\n| } | |\n| async function initialize(vid, fmt) { | |\n| console.log(\"→ initializing...\"); | |\n| const r = await req(`https://${EPS}/api/v1/init?_=${Date.now()}`, { Authorization: `Bearer ${key}` }); | |\n| if (r.error > 0) throw new Error(`init: ${r.error}`); | |\n| await convert(r.convertURL, vid, fmt, 0); | |\n| } | |\n| async function convert(cUrl, vid, fmt, redirected) { | |\n| const r = await req(`${cUrl}&v=${vid}&f=${fmt}&_=${Date.now()}`); | |\n| if (r.error > 0) throw new Error(`convert: ${r.error}`); | |\n| if (redirected === 1) { | |\n| return geo | |\n| ? waitProgress(r.progressURL, r.downloadURL, vid, fmt, r.title) | |\n| : download(r.downloadURL, vid, fmt, r.title); | |\n| } | |\n| if (r.redirect === 1) return convert(r.redirectURL, vid, fmt, 1); | |\n| await pollProgress(r.progressURL, r.downloadURL, vid, fmt); | |\n| } | |\n| const STATES = [\"checking video\", \"extracting video\", \"converting video\", \"done\"]; | |\n| async function pollProgress(pUrl, dlUrl, vid, fmt, prev = -1) { | |\n| const r = await req(`${pUrl}&_=${Date.now()}`); | |\n| if (r.error > 0) throw new Error(`progress: ${r.error}`); | |\n| if (r.title) console.log(` title: ${r.title}`); | |\n| if (r.progress !== prev) console.log(` ${STATES[r.progress] || r.progress}`); | |\n| if (r.progress < 3) { | |\n| await delay(3000); | |\n| return pollProgress(pUrl, dlUrl, vid, fmt, r.progress); | |\n| } | |\n| await download(dlUrl, vid, fmt); | |\n| } | |\n| async function waitProgress(pUrl, dlUrl, vid, fmt, title) { | |\n| for (const s of [\"extracting video\", \"converting video\"]) { | |\n| await delay(3000); | |\n| console.log(` ${s}`); | |\n| } | |\n| await download(dlUrl, vid, fmt, title); | |\n| } | |\n| async function download(dlUrl, vid, fmt, title) { | |\n| const safe = `${(title || vid).replace(/[/\\\\?%*:|\"<>]/g, \"_\")}.${fmt}`; | |\n| console.log(`\\n✓ downloading: ${safe}`); | |\n| const res = await fetch(`${dlUrl}&v=${vid}&f=${fmt}&r=cli`, { headers: HEADERS, redirect: \"follow\" }); | |\n| if (!res.ok) throw new Error(`download: HTTP ${res.status}`); | |\n| await pipeline(res.body, createWriteStream(safe)); | |\n| console.log(`✓ saved: ${safe}`); | |\n| } | |\n| const delay = (ms) => new Promise((r) => setTimeout(r, ms)); | |\n| function extractId(str) { | |\n| return (/(?:youtu\\.be\\/|youtube\\.com\\/(?:embed\\/|live\\/|shorts\\/)|[?&]v=)([a-zA-Z0-9-_]{11})/.exec(str) || [])[1] || null; | |\n| } | |\n| const vid = extractId(youtube); | |\n| if (!vid) { console.error(\"invalid URL\"); process.exit(1); } | |\n| if (FORMAT !== \"mp3\" && FORMAT !== \"mp4\") { console.error(\"invalid format\"); process.exit(1); } | |\n| console.log(`\\n→ processing [${vid}] as ${FORMAT}`); | |\n| try { await auth(vid, FORMAT); } | |\n| catch (e) { console.error(\"✗\", e.message); process.exit(1); } |", "url": "https://wpnews.pro/news/yt2mp3-gs-scrape-by-claidex-alfidev", "canonical_source": "https://gist.github.com/claidexdigital/b8635d80a8b934ab6998e4a1d42beb0c", "published_at": "2026-06-24 12:19:07+00:00", "updated_at": "2026-06-24 13:38:51.239675+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["claidex", "alfidev", "yt2mp3.gs", "epsilon.epsiloncloud.org", "YouTube"], "alternates": {"html": "https://wpnews.pro/news/yt2mp3-gs-scrape-by-claidex-alfidev", "markdown": "https://wpnews.pro/news/yt2mp3-gs-scrape-by-claidex-alfidev.md", "text": "https://wpnews.pro/news/yt2mp3-gs-scrape-by-claidex-alfidev.txt", "jsonld": "https://wpnews.pro/news/yt2mp3-gs-scrape-by-claidex-alfidev.jsonld"}}