A run is a single execution of an automation. When you call any TinyFish Web Agent endpoint, you create a run that moves through a lifecycle from start to finish.
Run Lifecycle
Every run moves through these statuses:
Status Meaning PENDINGQueued, waiting to start RUNNINGBrowser is executing your goal COMPLETEDFinished (check result for data) FAILEDInfrastructure error occurred CANCELLEDManually stopped
Cancellation is only supported for runs created via /run-async or /run-sse. Runs created via the synchronous /run endpoint cannot be cancelled because the request blocks until completion.
The Run Object
When you fetch a run, you get back the following object:
{
"run_id" : "abc123" ,
"status" : "COMPLETED" ,
"result" : { ... },
"error" : null ,
"streaming_url" : "https://tf-abc123.fra0-tinyfish.unikraft.app/stream/0"
}
Field Description run_idUnique identifier for this run statusCurrent lifecycle status resultYour extracted data (when COMPLETED) errorError details (when FAILED) streaming_urlURL to watch the browser live video_urlURL to the run recording, if available. null when no recording exists for this run.
Searching and Filtering Runs
GET /v1/runs supports filtering, text search, sorting, and pagination to help you find specific runs.
Query Parameters
Parameter Type Description statusstring Filter by status: PENDING, RUNNING, COMPLETED, FAILED, CANCELLED goalstring Search runs by goal text (case-insensitive partial match) created_afterISO 8601 Only return runs created after this timestamp created_beforeISO 8601 Only return runs created before this timestamp sort_directionasc | descSort order by creation date (default: desc) cursorstring Pagination cursor from a previous response limitnumber Results per page, 1–100 (default: 20)
Examples
Search by goal text:
curl "https://agent.tinyfish.ai/v1/runs?goal=linkedin" \
-H "X-API-Key: YOUR_API_KEY"
Filter by status and date range:
curl "https://agent.tinyfish.ai/v1/runs?status=COMPLETED&created_after=2026-01-01T00:00:00Z&created_before=2026-02-01T00:00:00Z" \
-H "X-API-Key: YOUR_API_KEY"
Oldest first with pagination:
curl "https://agent.tinyfish.ai/v1/runs?sort_direction=asc&limit=10" \
-H "X-API-Key: YOUR_API_KEY"
Response Shape
GET /v1/runs returns a data array of run objects and a pagination object:
{
"data" : [
{
"run_id" : "run_abc123" ,
"status" : "COMPLETED" ,
"url" : "https://example.com" ,
"goal" : "Extract the page title" ,
"started_at" : "2026-01-01T00:00:00Z" ,
"finished_at" : "2026-01-01T00:00:30Z"
}
],
"pagination" : {
"total" : 42 ,
"next_cursor" : null ,
"has_more" : false
}
}
When there are more results, the pagination object includes next_cursor:
{
"data" : [ ... ],
"pagination" : {
"total" : 142 ,
"next_cursor" : "eyJpZCI6..." ,
"has_more" : true
}
}
Pass next_cursor as the cursor parameter to fetch the next page.
Watching Runs Live
Every run includes a streaming_url where you can watch the browser execute in real-time. This is useful for debugging, demos, or showing users what’s happening behind the scenes.
Embed the URL in an iframe to display the live browser view in your app:
< iframe
src = "https://tf-abc123.fra0-tinyfish.unikraft.app/stream/0"
width = "800"
height = "600"
/ >
The streaming URL is valid for 24 hours after the run completes.
Retrieving Steps and Screenshots
?screenshots=base64 is available to unblock current integrations but is temporary — it will be deprecated soon in favor of URL-based access. Avoid building long-term workflows that depend on this format.
GET /v1/runs/{id} always returns a steps array. Pass ?screenshots=base64 to attach a screenshot to each step (~50–100 KB each — use only for audit trails or visual debugging).
curl "https://agent.tinyfish.ai/v1/runs/abc123?screenshots=base64" \
-H "X-API-Key: YOUR_API_KEY"
The response includes a steps array. Without screenshots, the screenshot field is null:
{
"run_id" : "abc123" ,
"status" : "COMPLETED" ,
"result" : { ... },
"steps" : [
{
"id" : "09de224d-fb2b-45b7-b067-585726194a2e" ,
"timestamp" : "2026-03-23T10:00:01Z" ,
"status" : "COMPLETED" ,
"action" : "Navigate to https://example.com" ,
"screenshot" : null ,
"duration" : "1.2s"
},
{
"id" : "3fa85f64-5717-4562-b3fc-2c963f66afa6" ,
"timestamp" : "2026-03-23T10:00:03Z" ,
"status" : "COMPLETED" ,
"action" : "Click the 'Sign In' button" ,
"screenshot" : "data:image/jpeg;base64,/9j/4AAQSkZJRgAB..." ,
"duration" : "0.8s"
}
]
}
Understanding COMPLETED Status
COMPLETED means the infrastructure worked, not that your goal succeeded.
Always check the result field:
Goal succeeded:
{
"status" : "COMPLETED" ,
"result" : {
"products" : [
{ "name" : "Widget" , "price" : 29.99 }
]
}
}
Infrastructure worked, goal failed:
The browser worked fine, but TinyFish Web Agent couldn’t achieve your goal.
{
"status" : "COMPLETED" ,
"result" : {
"status" : "failure" ,
"reason" : "Could not find any products on the page"
}
}
Handling Run Results
Use this pattern to handle both infrastructure failures and goal failures in your code.
import { TinyFish , RunStatus } from "@tiny-fish/sdk" ;
import type { Run } from "@tiny-fish/sdk" ;
const client = new TinyFish ();
// Fetch a run by ID, then handle the result
const run = await client . runs . get ( runId );
const result = await handleRunResult ( run );
async function handleRunResult ( run : Run ) {
switch ( run . status ) {
case RunStatus . COMPLETED :
if ( ! run . result ) {
return { success: false , error: "No result returned" };
}
// Check for goal-level failure in result
if ( run . result . status === "failure" || run . result . error ) {
return {
success: false ,
error: run . result . reason || run . result . error || "Goal not achieved" ,
};
}
return { success: true , data: run . result };
case RunStatus . FAILED :
return {
success: false ,
error: run . error ?. message || "Automation failed" ,
retryable: true ,
};
case RunStatus . CANCELLED :
return { success: false , error: "Run was cancelled" };
default :
return { success: false , error: `Unexpected status: ${ run . status } ` };
}
}
Cancelling Runs
You can cancel a run that is PENDING or RUNNING by sending a POST request to /v1/runs/{id}/cancel. This works for runs created via /run-async or /run-sse only.
const response = await fetch ( `https://agent.tinyfish.ai/v1/runs/ ${ run_id } /cancel` , {
method: "POST" ,
headers: {
"X-API-Key" : process . env . TINYFISH_API_KEY ,
},
});
const result = await response . json ();
// result.status: CANCELLED, COMPLETED, or FAILED
// result.cancelled_at: timestamp if cancelled
// result.message: additional context (e.g. "Run already cancelled")
The cancel endpoint is idempotent — calling it on an already-cancelled or completed run returns the current state without error.
Scenario Response status cancelled_atmessageRun cancelled CANCELLEDTimestamp nullAlready cancelled CANCELLEDTimestamp "Run already cancelled"Already completed COMPLETEDnull"Run already finished"
Only runs created via the API (/run-async or /run-sse) can be cancelled using this endpoint. Runs created through the dashboard UI or via the synchronous /run endpoint cannot be cancelled.
Endpoints Choose sync, async, or streaming
Error Codes Handle errors gracefully