decolua/9router · error

Failed to parse Bing token

Error message

Failed to parse Bing token

What it means

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.

Source

Thrown at open-sse/handlers/ttsProviders/edgeTts.js:23

const REFRESH_MS = 5 * 60 * 1000; // token TTL ~1h, refresh early
const VOICES_TTL = 24 * 60 * 60 * 1000;

const cache = { token: null, tokenTime: 0 };
let _voicesCache = null;
let _voicesCacheTime = 0;

async function getToken() {
  const now = Date.now();
  if (cache.token && now - cache.tokenTime < REFRESH_MS) return cache.token;
  const res = await fetch("https://www.bing.com/translator", {
    headers: { "User-Agent": UA, "Accept-Language": "vi,en-US;q=0.9,en;q=0.8" },
  });
  if (!res.ok) throw new Error(`Bing translator fetch failed: ${res.status}`);
  const rawCookies = res.headers.getSetCookie?.() || [];
  const cookie = rawCookies.map((c) => c.split(";")[0]).join("; ");
  const html = await res.text();
  const match = html.match(/params_AbusePreventionHelper\s*=\s*\[([^,]+),([^,]+),/);
  if (!match) throw new Error("Failed to parse Bing token");
  cache.token = { key: match[1], token: match[2].replace(/"/g, ""), cookie };
  cache.tokenTime = now;
  return cache.token;
}

async function ttsRequest(text, voiceId, token) {
  const parts = voiceId.split("-");
  const xmlLang = parts.slice(0, 2).join("-");
  const gender = voiceId.toLowerCase().includes("male") ? "Male" : "Female";
  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>`;
  const body = new URLSearchParams();
  body.append("ssml", ssml);
  body.append("token", token.token);
  body.append("key", token.key);
  return fetch("https://www.bing.com/tfettts?isVertical=1&&IG=1&IID=translator.5023&SFX=1", {
    method: "POST",
    body: body.toString(),
    headers: {

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. 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
  2. Check whether the response is a redirect/consent page; follow redirects or add the required cookies
  3. Use a different User-Agent or add Accept-Language headers matching a region that still serves the token
  4. Pin to a known-good mirror/proxy of the translator page, or switch to another TTS provider
  5. 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
Defensive patterns

Strategy: fallback

Validate before calling

const html = await (await fetch("https://www.bing.com/translator")).text();
if (!/params_AbusePreventionHelper/.test(html)) console.warn("Bing token missing from page — edgeTts parser likely outdated");

Try / catch

try {
  const audio = await edgeTts.synthesize(text, voice);
} catch (e) {
  if (e.message === "Failed to parse Bing token") return fallbackTts.synthesize(text, voice);
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/e0a24c1351369b12. Report an issue: GitHub.