{"record":{"id":"e0a24c1351369b12","repo":"decolua/9router","slug":"failed-to-parse-bing-token","errorCode":null,"errorMessage":"Failed to parse Bing token","messagePattern":"Failed to parse Bing token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"open-sse/handlers/ttsProviders/edgeTts.js","lineNumber":23,"sourceCode":"const REFRESH_MS = 5 * 60 * 1000; // token TTL ~1h, refresh early\nconst VOICES_TTL = 24 * 60 * 60 * 1000;\n\nconst cache = { token: null, tokenTime: 0 };\nlet _voicesCache = null;\nlet _voicesCacheTime = 0;\n\nasync function getToken() {\n  const now = Date.now();\n  if (cache.token && now - cache.tokenTime < REFRESH_MS) return cache.token;\n  const res = await fetch(\"https://www.bing.com/translator\", {\n    headers: { \"User-Agent\": UA, \"Accept-Language\": \"vi,en-US;q=0.9,en;q=0.8\" },\n  });\n  if (!res.ok) throw new Error(`Bing translator fetch failed: ${res.status}`);\n  const rawCookies = res.headers.getSetCookie?.() || [];\n  const cookie = rawCookies.map((c) => c.split(\";\")[0]).join(\"; \");\n  const html = await res.text();\n  const match = html.match(/params_AbusePreventionHelper\\s*=\\s*\\[([^,]+),([^,]+),/);\n  if (!match) throw new Error(\"Failed to parse Bing token\");\n  cache.token = { key: match[1], token: match[2].replace(/\"/g, \"\"), cookie };\n  cache.tokenTime = now;\n  return cache.token;\n}\n\nasync function ttsRequest(text, voiceId, token) {\n  const parts = voiceId.split(\"-\");\n  const xmlLang = parts.slice(0, 2).join(\"-\");\n  const gender = voiceId.toLowerCase().includes(\"male\") ? \"Male\" : \"Female\";\n  const ssml = `<speak version='1.0' xml:lang='${xmlLang}'><voice xml:lang='${xmlLang}' xml:gender='${gender}' name='${voiceId}'><prosody rate='0.00%'>${text}</prosody></voice></speak>`;\n  const body = new URLSearchParams();\n  body.append(\"ssml\", ssml);\n  body.append(\"token\", token.token);\n  body.append(\"key\", token.key);\n  return fetch(\"https://www.bing.com/tfettts?isVertical=1&&IG=1&IID=translator.5023&SFX=1\", {\n    method: \"POST\",\n    body: body.toString(),\n    headers: {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/handlers/ttsProviders/edgeTts.js#L5-L41","documentation":"After fetching the Bing translator page successfully, getToken() regex-extracts params_AbusePreventionHelper = [key, token, ...] from the HTML. If the pattern is absent it throws 'Failed to parse Bing token'. This means Bing served the page but did not embed the expected token — usually a page-structure change or a bot-detection interstitial.","triggerScenarios":"Bing changes the HTML template or renames params_AbusePreventionHelper; Bing returns a CAPTCHA/consent/redirect page instead of the translator page; the request was served a regional variant lacking the token script; the regex (which requires two comma-separated fields) no longer matches the embedded array.","commonSituations":"Bing deployed an update (Edge TTS token scraping breaks community-wide when this happens); running from a region where bing.com redirects to a consent page; datacenter IP served a challenge page with 200 status; stale cached HTML from a proxy.","solutions":["Update the regex in open-sse/handlers/ttsProviders/edgeTts.js to match the current page structure — fetch https://www.bing.com/translator and inspect where the token now lives","Check whether the response is a redirect/consent page; follow redirects or add the required cookies","Use a different User-Agent or add Accept-Language headers matching a region that still serves the token","Pin to a known-good mirror/proxy of the translator page, or switch to another TTS provider","Track the edge-tts community (e.g. edge-tts Python package issues) — when this breaks it is usually upstream-wide and fixed by matching their updated approach"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"const html = await (await fetch(\"https://www.bing.com/translator\")).text();\nif (!/params_AbusePreventionHelper/.test(html)) console.warn(\"Bing token missing from page — edgeTts parser likely outdated\");","typeGuard":null,"tryCatchPattern":"try {\n  const audio = await edgeTts.synthesize(text, voice);\n} catch (e) {\n  if (e.message === \"Failed to parse Bing token\") return fallbackTts.synthesize(text, voice);\n  throw e;\n}","preventionTips":["Pin/monitor the upstream edge-tts project for page-structure break reports","Keep a non-scraping TTS provider as fallback for production workloads","Add a startup health check that probes the Bing token once and alerts on parse failure","Avoid tight loops of synthesis that trigger Bing bot detection"],"tags":["tts","edge-tts","bing","scraping","parse-error"],"backgroundTag":"upstream-page-changed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}