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 from fire-engine checkStatus: the job's status.error string contains 'Chrome error: ' and the extracted code includes ERR_CERT_, ERR_SSL_, or ERR_BAD_SSL_. This is the CDP/browser path reporting a TLS failure while loading the page. The thrown SSLError carries meta.options.skipTlsVerification so the caller can be told how to bypass.

Source

Thrown at apps/api/src/scraper/scrapeURL/engines/fire-engine/checkStatus.ts:220

    ) {
      logger.info(
        "Scrape job signaled retryWithStealth. Adding stealthProxy flag.",
        { jobId },
      );
      throw new AddFeatureError(["stealthProxy"]);
    }
    if (
      typeof status.error === "string" &&
      status.error.includes("Chrome error: ")
    ) {
      const code = status.error.split("Chrome error: ")[1];

      if (
        code.includes("ERR_CERT_") ||
        code.includes("ERR_SSL_") ||
        code.includes("ERR_BAD_SSL_")
      ) {
        throw new SSLError(meta.options.skipTlsVerification);
      } else {
        throw new SiteError(code);
      }
    } else if (
      typeof status.error === "string" &&
      status.error.includes("proxies available for")
    ) {
      throw new ProxySelectionError();
    } else if (
      typeof status.error === "string" &&
      status.error.includes("Dns resolution error for hostname: ")
    ) {
      throw new DNSResolutionError(
        status.error.split("Dns resolution error for hostname: ")[1],
      );
    } else if (
      typeof status.error === "string" &&
      status.error.includes("File exceeds size limit")

View on GitHub (pinned to 656bffcc28)

Solutions

  1. Set skipTlsVerification: true in the scrape request for trusted sites.
  2. Try the http:// variant of the URL if available.
  3. Have the site operator fix the certificate (renew/rechain/fix SNI).
  4. If behind a corporate TLS-intercepting proxy, exempt Firecrawl or scrape from a non-intercepting network.

Example fix

// before
await scrapeURL({ url: 'https://self-signed.internal.example.com', engine: 'fire-engine' });

// after
await scrapeURL({ url: 'https://self-signed.internal.example.com', engine: 'fire-engine', skipTlsVerification: true });
Defensive patterns

Strategy: retry

Validate before calling

async function certLooksValid(url) {
  try { await fetch(url, { method: 'HEAD' }); return true; }
  catch (e) { return !(e?.cause?.code?.startsWith('ERR_CERT_') || e?.cause?.code?.startsWith('ERR_SSL_')); }
}

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, engine: 'fire-engine' });
} catch (e) {
  if (isSSLError(e) && isTrustedInternal(url)) {
    await scrapeURL({ url, engine: 'fire-engine', skipTlsVerification: true });
  } else throw e;
}

Prevention

When it happens

Trigger: A Chrome/CDP scrape (fire-engine checkStatus) whose page load fails with a Chrome network error in the certificate family. status.error looks like 'Chrome error: ERR_CERT_AUTHORITY_INVALID' or 'ERR_SSL_PROTOCOL_ERROR'; the substring checks at checkStatus.ts:214-217 match and throw SSLError.

Common situations: Self-signed internal sites; sites with expired/misconfigured certs; corporate proxies doing TLS interception; staging environments; sites that only present a valid cert to specific SNI values. Happens specifically on the browser path, distinct from the fetch-engine CERT_HAS_EXPIRED case.

Understand the failure class

Related errors


AI-assisted analysis of firecrawl/firecrawl@656bffcc28 (2026-08-12). Data as JSON: /api/errors/35593123b76efa74. Report an issue: GitHub.