puppeteer/puppeteer · error
Could not parse JSON from ${url}
Error message
Could not parse JSON from ${url} What it means
Thrown by getJSON when the body fetched from url could not be JSON.parse'd. The original SyntaxError is swallowed and replaced with a clearer message naming the URL. Because getText already handles HTTP-level errors (>=400), reaching JSON.parse means the request returned 2xx with a non-JSON body — typically an HTML error/landing page from a proxy or a misrouted URL.
Source
Thrown at packages/browsers/src/httpUtil.ts:171
}
});
response.pipe(file);
});
request.on('error', error => {
return reject(error);
});
} catch (error) {
reject(error);
}
});
}
export async function getJSON(url: URL): Promise<unknown> {
const text = await getText(url);
try {
return JSON.parse(text);
} catch {
throw new Error('Could not parse JSON from ' + url.toString());
}
}
export function getText(url: URL): Promise<string> {
return new Promise(async (resolve, reject) => {
try {
const request = await httpRequest(
url,
'GET',
response => {
let data = '';
if (response.statusCode && response.statusCode >= 400) {
return reject(new Error(`Got status code ${response.statusCode}`));
}
response.on('data', chunk => {
data += chunk;
});
response.on('end', () => {View on GitHub (pinned to d484e21c17)
Solutions
- Manually curl the URL and inspect Content-Type and the first bytes of the body.
- Correct baseUrl to the official endpoint or a mirror known to serve JSON.
- Bypass/whitelist the endpoint in your proxy to prevent HTML injection.
- Catch the error and fall back to a known-good pinned URL.
Defensive patterns
Strategy: try-catch
Validate before calling
async function bodyIsJson(url: URL): Promise<boolean> {
const res = await fetch(url);
const ct = res.headers.get('content-type') ?? '';
return ct.includes('application/json') && res.ok;
}
if (!await bodyIsJson(url)) throw new Error(`Endpoint ${url} does not serve JSON`); Try / catch
try {
return await getJSON(url);
} catch (e) {
if ((e as Error).message.startsWith('Could not parse JSON')) {
throw new Error(`${url} returned non-JSON (likely an HTML proxy/login page). Check baseUrl.`);
}
throw e;
} Prevention
- Confirm baseUrl serves application/json with a quick curl before installing.
- Whitelist browser endpoints in corporate proxies to avoid HTML injection.
- Keep baseUrl at the official endpoints unless you fully control the mirror.
When it happens
Trigger: A custom baseUrl returns HTML (login page, 200-status error page) instead of JSON; a corporate proxy intercepts with a captive portal; product-details / JSON endpoints moved and now 302 to an HTML page; trailing slash differences yielding a directory listing.
Common situations: Misconfigured baseUrl for Firefox product-details; storage bucket returning XML error JSON; localized ISP injection; the JSON endpoint changed path upstream.
Related errors
- Failed to download bisect-builds.py: ${response.statusText}
- ${error.message}
- ERROR: Failed to set up ${browser} v${buildId}! Set "PUPPETE
- .metadata is not an object
- Channel ${channel} is not found.
AI-assisted analysis of puppeteer/puppeteer@d484e21c17 (2026-08-12).
Data as JSON: /api/errors/a595f5ddceafbdb2.
Report an issue: GitHub.