Docs

HTTP API Reference

Base URL in development: http://127.0.0.1:4340.

All routes are implemented by createScrapeServer().handleRequest(req) and are rooted at /api/scrape/*.

GET /api/scrape/health

Returns component health.

Response body:

FieldTypeDescription
status`"ok" \"degraded" \"down"`Overall server status.
versionstringScrape server version.
components.engine`"ok" \"down"`Engine status.
components.driver`"ok" \"mock" \"down"`Browser driver status.
components.ai`"ok" \"mock" \"down"`AI bridge status.
components.safe`"ok" \"needs-auth" \"unavailable"`Credential provider status.
const response = await fetch("http://127.0.0.1:4340/api/scrape/health");
console.log(await response.json());

POST /api/scrape/jobs

Creates a job from a ScrapeRequest. The current server stores the request and returns a job ID; starting the run is a separate call.

Request body:

FieldTypeRequiredDescription
urlstringYesTarget URL.
intentstringYesPlain-text task.
mode`"auto" \"content" \"interactive" \"hybrid"`NoParsing mode.
schemaJsonSchemaNoDesired structured output shape.
authScrapeAuthRefNoAuth or session reference.
budgetScrapeBudgetNoStep/token/time budget fields.
emitScrapeEmitOptionsNoArtifact and view emission options.
interactionInteractionPolicyNoHuman-in-the-loop policy.
projectstringNoCaller project label.
captureSessionAsstringNoSafe ref to store browser storage state after success.

Response body:

{ "jobId": "job_1" }

POST /api/scrape/jobs/:jobId/run

Starts an asynchronous run for a previously created job.

Response body:

{ "runId": "run_2" }

GET /api/scrape/runs/:runId

Polls run status.

For in-flight runs, the response is an envelope:

{ "runId": "run_2", "status": "running" }

When a run needs a human response, the envelope includes interaction.

For terminal runs, the response is a full ScrapeResult with provenance, optional answer, optional artifact, optional interactions, and optional error.

const run = await fetch("http://127.0.0.1:4340/api/scrape/runs/run_2");
const body = await run.json();
console.log(body.status);

GET /api/scrape/runs/:runId/events

Returns the current run event buffer as text/event-stream.

The shipped client parses these blocks into ScrapeEvent[] through client.streamEvents(runId).

Event types currently emitted by the package:

TypeDescription
run.startedEngine run started.
run.stepA pipeline or action step was recorded.
run.view_readyMarkdown/HTML/element views are ready.
interaction.requiredHuman input is required.
interaction.resolvedHuman input was resolved or aborted.
run.healedSelector healing was attempted.
run.succeededRun completed successfully.
run.failedRun halted or failed.
artifact.createdA reusable artifact was emitted.

POST /api/scrape/runs/:runId/interactions/:interactionId

Submits an InteractionResponse for a parked run.

Request body examples:

{ "id": "int_1", "outcome": "aborted" }
{ "id": "int_1", "outcome": "resolved", "approved": true }

Response body:

{ "ok": true, "runId": "run_2", "interactionId": "int_1" }

If the interaction is not pending, the server returns 409 with ok: false.

GET /api/scrape/artifacts/:artifactId

Fetches an artifact emitted by a completed run.

Response body: ScrapeArtifact.

import { createScrapeClient } from "@cuitty/scrape/client";

const client = createScrapeClient({ mock: true });
const result = await client.run({ url: "https://example.com", intent: "Read the headline" });

if (result.artifact) {
  const artifact = await client.getArtifact(result.artifact.id);
  console.log(artifact.source.url);
}

Current Gaps

There is no shipped HTTP replay endpoint yet. Replay is available in-process through @cuitty/scrape/artifact.