Skip to main content
TinyFish Web Agent offers three ways to run automations. Each endpoint serves a different need. Pick the one that matches how you want to handle the request and response.

The Three Endpoints

EndpointPatternBest For
/runSynchronousQuick tasks, simple integrations
/run-asyncStart then checkLong tasks, batch processing
/run-sseLive updatesReal-time progress, user-facing apps

Synchronous: /run

Pattern: Send request → Wait → Get result The simplest approach. You call the API, it blocks until the automation completes, then returns the result.
const response = await fetch("https://agent.tinyfish.ai/v1/automation/run", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.TINYFISH_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com",
    goal: "Extract the page title",
  }),
});

const run = await response.json();
console.log(run.result); // Your data
  • Tasks that complete in under 30 seconds
  • Simple scripts and one-off automations
  • When you don’t need progress updates

Asynchronous: /run-async

Pattern: Send request → Get run ID → Poll for result The request returns immediately with a run_id. You then poll a separate endpoint to check status and get the result when ready. 1. Start the automation
const response = await fetch("https://agent.tinyfish.ai/v1/automation/run-async", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.TINYFISH_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com",
    goal: "Extract all product data",
  }),
});

const { run_id } = await response.json();
2. Poll for the result
const response = await fetch(`https://agent.tinyfish.ai/v1/runs/${run_id}`, {
  headers: { "X-API-Key": process.env.TINYFISH_API_KEY },
});

const run = await response.json();
// run.status: PENDING, RUNNING, COMPLETED, or FAILED
// run.result: Your data (when COMPLETED)
Learn more about run statuses and lifecycle in Runs.
  • Long-running automations (30+ seconds)
  • Batch processing multiple URLs
  • Fire-and-forget workflows
  • When you need to track runs separately

Streaming: /run-sse

Pattern: Send request → Receive event stream → Process events as they arrive Uses Server-Sent Events (SSE) to push updates to you in real-time. You’ll receive events for each action the browser takes, plus a streaming URL you can embed in an iframe to watch the automation live. 1. Start the automation
const response = await fetch("https://agent.tinyfish.ai/v1/automation/run-sse", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.TINYFISH_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com",
    goal: "Extract all product data",
  }),
});
2. Read the event stream
const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const text = decoder.decode(value);
  const lines = text.split("\n");

  for (const line of lines) {
    if (line.startsWith("data: ")) {
      const event = JSON.parse(line.slice(6));
      console.log(event.type, event);
    }
  }
}

Event Types

EventDescription
STARTEDAutomation has begun, includes runId
STREAMING_URLURL to watch the browser live (valid 24hrs)
PROGRESSBrowser action taken (click, type, scroll, etc.)
HEARTBEATConnection keep-alive (no action needed)
COMPLETEAutomation finished, includes status and resultJson

Handling Events

Use this pattern to process each event type as the automation progresses.
const eventHandlers = {
  STARTED: (event) => {
    console.log(`Run started: ${event.runId}`);
  },

  STREAMING_URL: (event) => {
    console.log(`Watch live: ${event.streamingUrl}`);
  },

  PROGRESS: (event) => {
    console.log(`Action: ${event.purpose}`);
  },

  COMPLETE: (event) => {
    if (event.status === "COMPLETED") {
      return event.resultJson;
    } else {
      throw new Error(event.error?.message || "Automation failed");
    }
  },

  HEARTBEAT: () => {
    // Connection is alive, no action needed
  },
};
  • User-facing apps (show progress)
  • When you want to watch the browser live
  • Debugging and development
  • Long tasks where you want visibility

Quick Decision Guide

1

Need real-time progress updates?

Yes → Use /run-sse
2

Task takes longer than 30 seconds?

Yes → Use /run-async + polling
3

Submitting multiple tasks at once?

Yes → Use /run-async (parallel submission)
4

Simple, quick task?

Use /run (synchronous)

Comparison Table

Feature/run/run-async/run-sse
Response typeFinal resultRun IDEvent stream
Progress updatesNoNo (poll status)Yes
Streaming URLIn responsePoll to getIn events
Best forQuick tasksBatch/long tasksReal-time UI
ComplexityLowMediumMedium