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 |
|---|
PENDING | Queued, waiting to start |
RUNNING | Browser is executing your goal |
COMPLETED | Finished (check result for data) |
FAILED | Infrastructure error occurred |
CANCELLED | Manually stopped |
The Run Object
When you fetch a run, you get back the following object:
{
"run_id": "abc123",
"status": "COMPLETED",
"result": { ... },
"error": null,
"streamingUrl": "https://stream.mino.ai/session/abc123"
}
| Field | Description |
|---|
run_id | Unique identifier for this run |
status | Current lifecycle status |
result | Your extracted data (when COMPLETED) |
error | Error details (when FAILED) |
streamingUrl | URL to watch the browser live |
Watching Runs Live
Every run includes a streamingUrl 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://stream.mino.ai/session/abc123"
width="800"
height="600"
/>
The streaming URL is valid for 24 hours after the run completes.
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.
async function handleTinyFishResponse(run: TinyFishRun) {
switch (run.status) {
case "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 "FAILED":
return {
success: false,
error: run.error?.message || "Automation failed",
retryable: true,
};
case "CANCELLED":
return { success: false, error: "Run was cancelled" };
default:
return { success: false, error: `Unexpected status: ${run.status}` };
}
}