firecrawl/firecrawl · error · SSLError
SCRAPE_SSL_ERROR
SCRAPE_SSL_ERROR
Error message
An SSL/TLS certificate error occurred while trying to establish a secure connection to this website. This usually happens when a website has an expired, self-signed, or misconfigured SSL certificate. If you trust this website and are not submitting sensitive data, you can bypass this error by setting `skipTlsVerification: true` in your scrape request. Note: Only do this for trusted sites as it disables certificate validation.
What it means
SSLError is raised by the plain fetch engine when the underlying Node fetch fails with a TypeError whose message is 'fetch failed' and whose cause carries code === 'CERT_HAS_EXPIRED'. It surfaces an expired TLS certificate on the target site. The remedy is exposed to the caller via meta.options.skipTlsVerification, which the SSLError message tells the user to enable. Note only the expired-cert branch maps here; other TypeError causes (including InsecureConnectionError) are rethrown unchanged.
Source
Thrown at apps/api/src/scraper/scrapeURL/engines/fetch/index.ts:207
headers: [...x.headers],
};
if (meta.mock === null) {
await saveMock(mockOptions, response);
}
} catch (error) {
if (
error instanceof TypeError &&
error.cause instanceof InsecureConnectionError
) {
throw error.cause;
} else if (
error instanceof Error &&
error.message === "fetch failed" &&
error.cause &&
(error.cause as any).code === "CERT_HAS_EXPIRED"
) {
throw new SSLError(meta.options.skipTlsVerification);
} else {
throw error;
}
}
}
await specialtyScrapeCheck(
meta.logger.child({ method: "scrapeURLWithFetch/specialtyScrapeCheck" }),
Object.fromEntries(response.headers as any),
);
return {
url: response.url,
html: response.body,
statusCode: response.status,
contentType:
(response.headers.find(x => x[0].toLowerCase() === "content-type") ??
[])[1] ?? undefined,View on GitHub (pinned to 656bffcc28)
Solutions
- Set skipTlsVerification: true in the scrape options if you trust the site and are not submitting sensitive data.
- Verify the site's certificate with curl -vI https://host and ask the site admin to renew if it is genuinely expired.
- Try the http:// URL instead if the site is reachable over plain HTTP.
- Correct an inaccurate system clock on the scraping host, which can cause valid certs to appear expired.
Example fix
// before
await scrapeURL({ url: 'https://internal-staging.example.com/data' });
// after — skip TLS verification for a trusted internal site
await scrapeURL({ url: 'https://internal-staging.example.com/data', skipTlsVerification: true }); Defensive patterns
Strategy: validation
Validate before calling
async function probeTls(url) {
try {
const res = await fetch(url, { method: 'HEAD' });
return { ok: true, status: res.status };
} catch (e) {
if (e?.cause?.code === 'CERT_HAS_EXPIRED') return { ok: false, reason: 'expired-cert' };
return { ok: false, reason: String(e?.message ?? e) };
}
} Type guard
import { SSLError } from '../error';
function isSSLError(e) {
return e instanceof SSLError || (e instanceof Error && e.name === 'SSLError');
} Try / catch
try {
await scrapeURL({ url });
} catch (e) {
if (isSSLError(e) && isTrustedInternal(url)) {
await scrapeURL({ url, skipTlsVerification: true });
} else throw e;
} Prevention
- Keep a safelist of trusted internal hosts for which skipTlsVerification is acceptable.
- Monitor target certs' expiry dates and renew before scraping breaks.
- Confirm the scraping host's system clock is correct — clock skew causes false CERT_HAS_EXPIRED.
When it happens
Trigger: A scrape that falls through to the fetch engine (no Chrome required) against an https URL whose certificate has expired. Node's undici fetch throws TypeError('fetch failed') with error.cause.code === 'CERT_HAS_EXPIRED'; the catch at fetch/index.ts:195-210 matches it and throws SSLError(skipTlsVerification). InsecureConnectionError causes are rethrown as-is and do not become SSLError.
Common situations: Scraping a small/stale site whose cert lapsed; internal/staging domains with self-signed certs that also report as expired; a site mid-renewal; CI where the runner clock is wrong and treats a valid cert as expired. Developers often hit this when moving from a browser-tolerant scrape to the lightweight fetch path.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
AI-assisted analysis of firecrawl/firecrawl@656bffcc28 (2026-08-12).
Data as JSON: /api/errors/f034ffcc59b5ee4b.
Report an issue: GitHub.