# Scrapfly Documentation

## Table of Contents

### Dashboard

- [Intro](https://scrapfly.io/docs)
- [Project](https://scrapfly.io/docs/project)
- [Account](https://scrapfly.io/docs/account)
- [Workspace & Team](https://scrapfly.io/docs/workspace-and-team)
- [Billing](https://scrapfly.io/docs/billing)

### Products

#### MCP Server

- [Getting Started](https://scrapfly.io/docs/mcp/getting-started)
- [Tools & API Spec](https://scrapfly.io/docs/mcp/tools)
- [Authentication](https://scrapfly.io/docs/mcp/authentication)
- [Examples & Use Cases](https://scrapfly.io/docs/mcp/examples)
- [FAQ](https://scrapfly.io/docs/mcp/faq)
##### Integrations

- [Overview](https://scrapfly.io/docs/mcp/integrations)
- [Claude Desktop](https://scrapfly.io/docs/mcp/integrations/claude-desktop)
- [Claude Code](https://scrapfly.io/docs/mcp/integrations/claude-code)
- [ChatGPT](https://scrapfly.io/docs/mcp/integrations/chatgpt)
- [Cursor](https://scrapfly.io/docs/mcp/integrations/cursor)
- [Cline](https://scrapfly.io/docs/mcp/integrations/cline)
- [Windsurf](https://scrapfly.io/docs/mcp/integrations/windsurf)
- [Zed](https://scrapfly.io/docs/mcp/integrations/zed)
- [Roo Code](https://scrapfly.io/docs/mcp/integrations/roo-code)
- [VS Code](https://scrapfly.io/docs/mcp/integrations/vscode)
- [LangChain](https://scrapfly.io/docs/mcp/integrations/langchain)
- [LlamaIndex](https://scrapfly.io/docs/mcp/integrations/llamaindex)
- [CrewAI](https://scrapfly.io/docs/mcp/integrations/crewai)
- [OpenAI](https://scrapfly.io/docs/mcp/integrations/openai)
- [n8n](https://scrapfly.io/docs/mcp/integrations/n8n)
- [Make](https://scrapfly.io/docs/mcp/integrations/make)
- [Zapier](https://scrapfly.io/docs/mcp/integrations/zapier)
- [Vapi AI](https://scrapfly.io/docs/mcp/integrations/vapi)
- [Agent Builder](https://scrapfly.io/docs/mcp/integrations/agent-builder)
- [Custom Client](https://scrapfly.io/docs/mcp/integrations/custom-client)


#### Web Scraping API

- [Getting Started](https://scrapfly.io/docs/scrape-api/getting-started)
- [API Specification]()
- [Monitoring](https://scrapfly.io/docs/monitoring)
- [Customize Request](https://scrapfly.io/docs/scrape-api/custom)
- [Debug](https://scrapfly.io/docs/scrape-api/debug)
- [Anti Scraping Protection](https://scrapfly.io/docs/scrape-api/anti-scraping-protection)
- [Proxy](https://scrapfly.io/docs/scrape-api/proxy)
- [Proxy Mode](https://scrapfly.io/docs/scrape-api/proxy-mode)
- [Proxy Mode - Screaming Frog](https://scrapfly.io/docs/scrape-api/proxy-mode/screaming-frog)
- [Proxy Mode - Apify](https://scrapfly.io/docs/scrape-api/proxy-mode/apify)
- [(Auto) Data Extraction](https://scrapfly.io/docs/scrape-api/extraction)
- [Javascript Rendering](https://scrapfly.io/docs/scrape-api/javascript-rendering)
- [Javascript Scenario](https://scrapfly.io/docs/scrape-api/javascript-scenario)
- [SSL](https://scrapfly.io/docs/scrape-api/ssl)
- [DNS](https://scrapfly.io/docs/scrape-api/dns)
- [Cache](https://scrapfly.io/docs/scrape-api/cache)
- [Batch (Multi-URL Scraping)](https://scrapfly.io/docs/scrape-api/batch)
- [Session](https://scrapfly.io/docs/scrape-api/session)
- [Webhook](https://scrapfly.io/docs/scrape-api/webhook)
- [Schedule](https://scrapfly.io/docs/scrape-api/schedule)
- [Screenshot](https://scrapfly.io/docs/scrape-api/screenshot)
- [Errors](https://scrapfly.io/docs/scrape-api/errors)
- [Timeout](https://scrapfly.io/docs/scrape-api/understand-timeout)
- [Throttling](https://scrapfly.io/docs/throttling)
- [Troubleshoot](https://scrapfly.io/docs/scrape-api/troubleshoot)
- [Billing](https://scrapfly.io/docs/scrape-api/billing)
- [FAQ](https://scrapfly.io/docs/scrape-api/faq)

#### Crawler API

- [Getting Started](https://scrapfly.io/docs/crawler-api/getting-started)
- [API Specification]()
- [Retrieving Results](https://scrapfly.io/docs/crawler-api/results)
- [WARC Format](https://scrapfly.io/docs/crawler-api/warc-format)
- [Data Extraction](https://scrapfly.io/docs/crawler-api/extraction-rules)
- [Webhook](https://scrapfly.io/docs/crawler-api/webhook)
- [Schedule](https://scrapfly.io/docs/crawler-api/schedule)
- [Billing](https://scrapfly.io/docs/crawler-api/billing)
- [Errors](https://scrapfly.io/docs/crawler-api/errors)
- [Troubleshoot](https://scrapfly.io/docs/crawler-api/troubleshoot)
- [FAQ](https://scrapfly.io/docs/crawler-api/faq)

#### Screenshot API

- [Getting Started](https://scrapfly.io/docs/screenshot-api/getting-started)
- [API Specification]()
- [Accessibility Testing](https://scrapfly.io/docs/screenshot-api/accessibility)
- [Webhook](https://scrapfly.io/docs/screenshot-api/webhook)
- [Schedule](https://scrapfly.io/docs/screenshot-api/schedule)
- [Billing](https://scrapfly.io/docs/screenshot-api/billing)
- [Errors](https://scrapfly.io/docs/screenshot-api/errors)

#### Extraction API

- [Getting Started](https://scrapfly.io/docs/extraction-api/getting-started)
- [API Specification]()
- [Rules Template](https://scrapfly.io/docs/extraction-api/rules-and-template)
- [LLM Extraction](https://scrapfly.io/docs/extraction-api/llm-prompt)
- [AI Auto Extraction](https://scrapfly.io/docs/extraction-api/automatic-ai)
- [Webhook](https://scrapfly.io/docs/extraction-api/webhook)
- [Billing](https://scrapfly.io/docs/extraction-api/billing)
- [Errors](https://scrapfly.io/docs/extraction-api/errors)
- [FAQ](https://scrapfly.io/docs/extraction-api/faq)

#### Data API


#### Proxy Saver

- [Getting Started](https://scrapfly.io/docs/proxy-saver/getting-started)
- [Fingerprints](https://scrapfly.io/docs/proxy-saver/fingerprints)
- [Optimizations](https://scrapfly.io/docs/proxy-saver/optimizations)
- [SSL Certificates](https://scrapfly.io/docs/proxy-saver/certificates)
- [Protocols](https://scrapfly.io/docs/proxy-saver/protocols)
- [Pacfile](https://scrapfly.io/docs/proxy-saver/pacfile)
- [Secure Credentials](https://scrapfly.io/docs/proxy-saver/security)
- [Billing](https://scrapfly.io/docs/proxy-saver/billing)

#### Cloud Browser API

- [Getting Started](https://scrapfly.io/docs/cloud-browser-api/getting-started)
- [Proxy & Geo-Targeting](https://scrapfly.io/docs/cloud-browser-api/proxy)
- [Unblock API](https://scrapfly.io/docs/cloud-browser-api/unblock)
- [Captcha Solver](https://scrapfly.io/docs/cloud-browser-api/captcha-solver)
- [File Downloads](https://scrapfly.io/docs/cloud-browser-api/file-downloads)
- [Session Resume](https://scrapfly.io/docs/cloud-browser-api/session-resume)
- [Human-in-the-Loop](https://scrapfly.io/docs/cloud-browser-api/human-in-the-loop)
- [Debug Mode](https://scrapfly.io/docs/cloud-browser-api/debug-mode)
- [Browser Extensions](https://scrapfly.io/docs/cloud-browser-api/extensions)
- [Native Browser MCP](https://scrapfly.io/docs/cloud-browser-api/mcp)
- [DevTools Protocol](https://scrapfly.io/docs/cloud-browser-api/cdp-reference)
##### Integrations

- [Puppeteer](https://scrapfly.io/docs/cloud-browser-api/puppeteer)
- [Playwright](https://scrapfly.io/docs/cloud-browser-api/playwright)
- [Selenium](https://scrapfly.io/docs/cloud-browser-api/selenium)
- [Vercel Agent Browser](https://scrapfly.io/docs/cloud-browser-api/agent-browser)
- [Browser Use](https://scrapfly.io/docs/cloud-browser-api/browser-use)
- [Stagehand](https://scrapfly.io/docs/cloud-browser-api/stagehand)

- [Billing](https://scrapfly.io/docs/cloud-browser-api/billing)
- [Errors](https://scrapfly.io/docs/cloud-browser-api/errors)


### Tools

- [Antibot Detector](https://scrapfly.io/docs/tools/antibot-detector)

### SDK

- [Golang](https://scrapfly.io/docs/sdk/golang)
- [Python](https://scrapfly.io/docs/sdk/python)
- [Rust](https://scrapfly.io/docs/sdk/rust)
- [TypeScript](https://scrapfly.io/docs/sdk/typescript)
- [Scrapy](https://scrapfly.io/docs/sdk/scrapy)

### Integrations

- [Getting Started](https://scrapfly.io/docs/integration/getting-started)
- [LangChain](https://scrapfly.io/docs/integration/langchain)
- [LlamaIndex](https://scrapfly.io/docs/integration/llamaindex)
- [CrewAI](https://scrapfly.io/docs/integration/crewai)
- [Zapier](https://scrapfly.io/docs/integration/zapier)
- [Make](https://scrapfly.io/docs/integration/make)
- [n8n](https://scrapfly.io/docs/integration/n8n)

### Academy

- [Overview](https://scrapfly.io/academy)
- [Web Scraping Overview](https://scrapfly.io/academy/scraping-overview)
- [Tools](https://scrapfly.io/academy/tools-overview)
- [Reverse Engineering](https://scrapfly.io/academy/reverse-engineering)
- [Static Scraping](https://scrapfly.io/academy/static-scraping)
- [HTML Parsing](https://scrapfly.io/academy/html-parsing)
- [Dynamic Scraping](https://scrapfly.io/academy/dynamic-scraping)
- [Hidden API Scraping](https://scrapfly.io/academy/hidden-api-scraping)
- [Headless Browsers](https://scrapfly.io/academy/headless-browsers)
- [Hidden Web Data](https://scrapfly.io/academy/hidden-web-data)
- [JSON Parsing](https://scrapfly.io/academy/json-parsing)
- [Data Processing](https://scrapfly.io/academy/data-processing)
- [Scaling](https://scrapfly.io/academy/scaling)
- [Walkthrough Summary](https://scrapfly.io/academy/walkthrough-summary)
- [Scraper Blocking](https://scrapfly.io/academy/scraper-blocking)
- [Proxies](https://scrapfly.io/academy/proxies)

---

#  Alert State Machine

 Every alert moves through a set of defined states. Understanding these states and the transitions between them tells you exactly when a notification fires, when it does not, and what to expect after you snooze or edit an alert.

## States

 | State | Badge | Meaning | Notifications fire? |
|---|---|---|---|
| **OK** | OK | Metric is within threshold. Everything is fine. | Only the one-time "resolved" notification when entering OK from TRIGGERED. |
| **PENDING** | PENDING | Threshold has been breached on at least one evaluation, but the `sustained_minutes` window has not fully elapsed yet. The alert is watching to see if the breach holds. | No. |
| **TRIGGERED** | TRIGGERED | The breach has been continuous for the full `sustained_minutes`. The alert is actively firing. | Yes: one notification on entry, then one every `renotify_minutes` (capped at 6/day). |
| **RECOVERING** | RECOVERING | Metric is back within threshold, but the `recovery_minutes` window has not elapsed yet. The alert is holding before declaring resolution. If the breach returns before the window elapses, the alert goes back to TRIGGERED. | No. |
| **SNOOZED** | SNOOZED | The user has muted this alert until a specific time or until resolved. The evaluator and audit log continue as normal. | No, until the snooze expires. |
| **NO\_DATA** | NO\_DATA | The evaluation window returned no data for this metric. Behavior depends on the `no_data_policy`. | Only if `no_data_policy = triggered`. |

## Transition diagram

### Main flow

 The normal path of an alert is a four-state cycle. A breach moves the alert from OK into PENDING. If the breach holds for `sustained_minutes`, the alert enters TRIGGERED and fires its first notification. When the metric clears, the alert either returns to OK immediately (if `recovery_minutes = 0`) or passes through RECOVERING for the recovery window first.

 Edge labels on the diagram are intentionally short for legibility. The precise condition for each transition (including the `recovery_minutes` threshold that distinguishes *cleared (fast)* from *cleared*) is listed in the [transition table](#transition-table) below. While the alert is in TRIGGERED, a re-notification fires every `renotify_minutes`, capped at six per day.

### Overlays: SNOOZED and NO\_DATA

 Two states sit on top of the normal flow and can be entered or left from any of the four main states. SNOOZED is triggered by the user (or automatically when the alert is edited); NO\_DATA is triggered when an evaluation tick returns no data for the metric.

 While SNOOZED, the evaluator keeps running and the audit log keeps writing, but no notification is sent until the snooze expires. What happens during NO\_DATA depends on the `no_data_policy` field. See [No-data policy](#no-data-policy) below.

## Transition table

 | From state | Condition | To state | Notification? |
|---|---|---|---|
| OK | Metric breaches threshold | PENDING | No |
| PENDING | Metric recovers before sustained window elapses | OK | No |
| PENDING | Breach continuous for `sustained_minutes` | TRIGGERED | **Yes** (first notification) |
| TRIGGERED | Metric back within threshold (`recovery_minutes = 0`) | OK | **Yes** (resolved notification) |
| TRIGGERED | Metric back within threshold (`recovery_minutes > 0`) | RECOVERING | No |
| TRIGGERED | `renotify_minutes` elapsed, still breached, below daily cap | TRIGGERED (stays) | **Yes** (re-notify) |
| RECOVERING | Breach returns before `recovery_minutes` elapses | TRIGGERED | No (was already TRIGGERED before RECOVERING) |
| RECOVERING | Metric stays within threshold for `recovery_minutes` | OK | **Yes** (resolved notification) |
| Any | User clicks Snooze | SNOOZED | No |
| SNOOZED | Snooze duration expires (or alert resolved if `until_resolved`) | Previous state (or OK) | No (resumes normal evaluation from here) |

## No-data policy

 When the evaluation window returns no data, there is no metric value to compare against the threshold. The `no_data_policy` field controls what happens:

 | Policy | Behavior | When to use |
|---|---|---|
| `ignore` (default) | Keep the current state unchanged. The evaluator skips this tick. | Most metrics. A data gap (telemetry lag, holiday low-traffic) should not change the alert state. |
| `triggered` | Treat no data as a breach. Forces TRIGGERED with a notification. | Liveness checks. Pair with `scheduler.no_executions` to alert when a schedule stops producing executions entirely. Also useful for "my scraper should always be running" scenarios. |
| `ok` | Treat no data as healthy. Forces OK, firing a resolved notification if was TRIGGERED. | Rarely used. Appropriate only when data absence genuinely means "nothing is broken" (for example, a metric that only exists when errors occur). |

## SNOOZED state in detail

 SNOOZED is an overlay, not a state in the linear machine. When snoozed:

- The evaluator keeps running on the normal schedule and every tick is recorded in the alert's audit history.
- State transitions (PENDING, TRIGGERED, RECOVERING, OK) still happen internally, but **no notification is sent** until the snooze expires.
- When the snooze lifts, the alert immediately resumes from its current actual state. If it is in TRIGGERED, the next re-notify tick will fire a notification.
- Editing an alert triggers an auto-snooze for `sustained_minutes` minutes. See [auto-snooze on edit](https://scrapfly.io/docs/alerting/anti-spam#auto-snooze-on-edit).

## Evaluation errors

 If a query times out or returns an error ([`ERR::ALERT::EVAL_TIMEOUT`](https://scrapfly.io/docs/alerting/error/ERR::ALERT::EVAL_TIMEOUT)), the tick is recorded in the audit log and the alert state is **not changed**. The next scheduled tick picks up from the unchanged state. This means a transient infrastructure blip cannot cause a false alert transition.

 [ Anti-Spam Controls ](https://scrapfly.io/docs/alerting/anti-spam) [ Back to Getting Started ](https://scrapfly.io/docs/alerting/getting-started)
