# Kaabist > Kaabist is a web automation API: it runs tasks on websites for you, even behind a login (signing in, filling in forms, downloading files, extracting data as JSON). Each task is built once as a versioned program, three ways: by clicking through the site in the visual builder (a recorder and a data picker in a live browser, with the step list and the JSON side by side), by a coding agent (Claude Code, Codex, Cursor) over MCP, or written as JSON and pushed with the API, SDKs or CLI. Kaabist runs it on a schedule, on an API call or as a batch. When a site asks for a 2FA code, the run pauses and Kaabist emails a link to the user (or a teammate or customer they choose) and continues from its last checkpoint once the code is typed. When a site changes, Kaabist finds the moved element and proposes the fix for the user to approve. A step that submits or pays never runs twice, even after a crash. Made in Istanbul. Documentation: https://docs.kaab.ist --- # Automate any website. It keeps working when the site changes. Sign-ins, forms, downloads and data, built once. When a page moves a button, Kaabist finds it again, finishes the run, and asks you to approve the fix. Free to start EU region Signed webhooks ## Most automation breaks the week a site ships a redesign. Kaabist is built for the weeks after: it resumes where it stopped, never repeats a payment, and runs the same program however you built it. - **Resumes where it stopped** The site asks for a code. You get a link, type it, and the run picks up at the same step. - **Never submits twice** A crash halfway through a payment never pays twice. The run stops at the fence and you decide. - **Built your way** In the visual builder, by your coding agent, or as JSON. The same program, the same guarantees. ## Sites change. Your automation doesn’t. Every step keeps a picture of what it clicked. When the page moves, Kaabist ranks what is there now, uses the closest match to finish the run, and keeps the old locator until you approve the new one. - **Signed webhooks** Every result reaches your server, retried until it lands. - **Take over anytime** Watch a run live and step in when you want. - **Typed data** Prices, dates and links come back parsed and checked, with a warning when a value looks wrong. - **Warned before it breaks** Canary runs and fill rates notice a changed site before your own runs fail. - **Popups out of the way** Cookie banners, modals and product tours are closed before they block a click. - **Dry runs and test keys** Try a program up to its first submit, or with test keys on their own small daily quota. - **Batches** Send up to 1,000 inputs in one call and follow them as one batch. - **Finds the hidden API** Spots the JSON behind the page and skips the browser next time. - **Bring your own** Use your own proxies, LLM or captcha solver, and that line leaves your bill. - **Stays signed in** Logs in once, runs on a schedule, and tells you only when something changed. ## One line to connect. Your agent does the rest. Your agent writes the program, tests it and schedules it. What you get back is a versioned program you can read, diff and run from any SDK. ## What’s inside the box. The limits you would ask about before you build on it. | Spec | Value | |---|---| | tiers: http, browser, stealth | 3 | | steps per program | 200 | | per download, response or PDF | 64 MB | | inputs per batch call | 1,000 | | Regions | eu, us | | Engines | Chromium; Firefox on the stealth tier | | Program size | 256 KB, nesting depth 3 | | Results | JSON response or signed webhook | | SDKs | TypeScript, Python, Go, CLI, REST, MCP | | Viewport | 1280 × 800, desktop or mobile profile | ## Recently shipped. The latest four. ## You were going to ask. So here’s the answer. - **What does Kaabist do?** It runs your website tasks (signing in, filling in forms, downloading files, pulling out data) and keeps them working when the site changes. - **Do I need to write code?** No. Click through the site in the visual builder, or tell your coding agent what you need. If you prefer code, write the program as JSON and use the API, SDKs or CLI. - **Can I see and change what it does?** Yes. A program is a list of steps and the same JSON, versioned with a diff. Edit either in the builder and test a step before you publish. - **What about 2FA codes?** The run pauses and Kaabist emails a link to you, or to a teammate or customer you choose. Type the code and it continues. - **Can a retry submit a form twice?** No. If something crashes mid-submit, Kaabist stops and asks you instead of clicking again. ## Bring your hardest site. Free to start. --- # Resumes where it stopped: Parks on a 2FA code. Picks up from its checkpoint. Some steps only you can finish: a one-time code, a captcha, an approval. Kaabist pauses the run right there and emails a link to you, or to the teammate or customer you choose. Once they answer, the program continues from its last checkpoint. Nothing starts over. ## Step by step 1. **The job logs in** The program opens the portal and fills in the email and the password, the way it always does. 2. **The site asks for a code** A one-time code goes to your phone. The program cannot know it, so the run pauses and waits for the code, with its place kept. 3. **You get a link** Kaabist emails you a page with one field and a button, or your teammate or customer: whoever gets the code. 4. **You type the code** The code goes straight to the waiting run. Nothing else in your system had to change. 5. **The run continues where it was** It continues from its checkpoint, not from the start: the login is not done twice, nothing before it runs again. 6. **And carries on** The report is read and returned as typed data. One run, one login, one code typed once. ## Ask where the flow needs it Put an await_input step where the site asks for something only you (or your customer) have. The browser stays open for a few minutes in case the answer comes quickly, and the job keeps waiting until the expiry you set: 24 hours by default, 7 days at most. ``` { "await_input": { "name": "otp", "type": "secret", "ttl": "5m", "expires": "24h", "collect": "hosted" } }, { "fill": "#otp", "value": "{{vars.otp}}" } ``` ## Answer from a link, or from your code With collect set to hosted, Kaabist emails a link to the address you choose: yours, a teammate's or your customer's. They open a page on app.kaab.ist, see what the run is waiting for, and type the answer. Your own code can answer instead, with one call. ``` curl -X POST https://api.kaab.ist/v1/jobs/job_8KqV2/input \ -H "Authorization: Bearer $KAAB_API_KEY" \ -d '{"otp": "481207"}' ``` ## Checkpoints, not restarts A checkpoint saves the browser's storage, the URL, the step and the variables. If the browser has closed by the time the answer arrives, Kaabist rebuilds the context from the checkpoint and carries on from the step after it. ``` { "click": { "role": "button", "name": "Sign in" } }, { "checkpoint": "after_login" } ``` ## When the unexpected happens An unknown page, a button that moved or a captcha pauses the run as needs attention, with a snapshot, a screenshot and suggested fixes. You can take over the live browser from your panel and continue, apply a fix, or retry from a named checkpoint. ``` curl -X POST https://api.kaab.ist/v1/jobs/job_8KqV2/resume \ -H "Authorization: Bearer $KAAB_API_KEY" \ -d '{"retry_from": "after_login"}' ``` ## Questions ### How long does a paused run wait? A planned wait (await_input) lasts until its expiry: 24 hours by default, up to 7 days. An unplanned stop (needs attention) keeps its checkpoint for 7 days. ### Does a paused run use credits while it waits? No. A paused run holds no reserved credits; it reserves again when it resumes. ### Who can answer a hosted page? Whoever you send the link to: you, a teammate, your customer. They need no Kaabist account, and the page shows only what the run is waiting for. Nobody at Kaabist answers for you. --- # Visual builder and recorder: Click through it once. It becomes a program. Record the task in a live Kaabist browser, pick the data you want, and edit the steps and the JSON side by side. Test any step against the real site before you publish. No agent and no code needed, and nothing hidden when you want them. ## Step by step 1. **Start the way you like** A blank program, a URL and a first field, a JSON file you have, or a recording. 2. **Record in a live browser** Click through the site in a live Kaabist browser. Each action becomes a step; a password becomes a secret input. 3. **Pick the data** Point at a value to pick it. Select similar turns one row into the whole list. 4. **Steps and JSON, in step** The step list and the JSON are one program. Edit either; the other follows. 5. **Test it on the real site** Run one step, or up to here, or replay a stored page. A dry run stops before any submit. 6. **Publish a version** Each publish is a version with a diff. Move an alias to roll out, or back. ## Record, don’t write The recorder watches what you do in the live browser: it saves each click and field as a step with several locators to fall back on, turns password values into secret inputs, suggests a wait for a one-time code, and proposes checks that the page looks right. ``` goto portal.example.com/login fill Email ← inputs.email fill Password ← inputs.password (secret) click Sign in await one-time code (hosted page) extract invoices[] · invoice, total (money) ``` ## Pick data like a person Hover to highlight, click to pick. Select similar builds a list from one example, you can move to a parent or child element, and Ctrl-click freezes a menu that only shows on hover. On a stored page, the snapshot picker builds the fields without running the site again. ``` "invoices": { "selector": "tbody tr", "many": true, "fields": { "invoice": "td:nth-child(1)", "total": { "selector": "td.total", "type": "money" } } } ``` ## Three control nodes, not a canvas A program stays a readable list: when for a condition, loop until for a repeat, paginate for the next page. The same JSON goes to the API, the CLI and your agent, so a program built here can be pulled into git and pushed back. ``` $ kaab programs pull supplier-invoices $ kaab programs diff supplier-invoices.json $ kaab programs push supplier-invoices.json ``` ## Questions ### Do I need to write code? No. Record the task, pick the data, test it and publish. The JSON is there when you want to read or change it. ### Can I mix the builder with my coding agent or the CLI? Yes. They all edit the same program. Your agent can draft it, you can fix a step in the builder, and a teammate can push the next version from git. ### Where do passwords go? Never into the program. A password you type while recording becomes a secret input, given at run time and kept out of logs, snapshots and screenshots. --- # Built by your coding agent: One line in your agent. A program in your account. Connect Claude Code, Codex or Cursor to mcp.kaab.ist. Your agent opens a real Kaabist browser, works through the site with you, and what it does becomes a program: versioned, linted, and tested with a dry run before it ever submits anything. ## Step by step 1. **You ask your agent** In Claude Code, Codex or Cursor, you describe what you need from a site, in plain words. 2. **It opens a real browser** Over MCP, the agent opens a Kaabist browser and reads the page as a view with ranked locators, not as pixels. 3. **It acts on the page** It fills, clicks and waits the way you would, and clears whatever covers the page first. 4. **It tries the extraction** Fields are tried on the live page, so the agent sees real values before anything is saved. 5. **What it did becomes a program** The session turns into a versioned program: the steps, the locators with their fallbacks, the typed fields. 6. **Tested, then published** It is linted and tested as a dry run, then pushed. From now on it runs without the agent, on a schedule or a call. ## Connect once The server speaks Streamable HTTP and signs your agent in with OAuth on your Kaabist account. You decide what it may do. It starts in test mode, on drafts, with a credit cap. ``` claude mcp add --transport http kaab https://mcp.kaab.ist/mcp ``` ## A real browser, not a guess The agent drives a browser on Kaabist's own pool and reads a condensed view of the page: forms, lists, landmarks, and ranked locator candidates for every element. You can watch it work in the panel, or take over at any moment. ``` › browser_open https://portal.example.test/login › browser_page_view forms: login (#email, #password, button "Sign in") › browser_fill e12 "{{inputs.email}}" › browser_click e15 ``` ## From session to program browser_to_program turns what the agent did into a draft program. lint_program checks it. test_program runs it as a dry run that stops before the first step that submits anything. You approve before it is published. ``` › browser_to_program → draft prg_4Rb v1 (7 steps) › lint_program → 0 errors, 1 warning › test_program → dry run stopped before click Renew ``` ## Questions ### Which agents work with it? Any MCP client that speaks Streamable HTTP and OAuth, Claude Code, Codex and Cursor among them. ### Can the agent run live jobs or publish on its own? Only with the scopes you grant. By default it works in test mode on drafts; publishing and steps that submit need scopes you approve. ### Where do secrets go? Never into the program. The program reads them as inputs at run time, and password fields are never shown back to the agent. --- # Never submits twice: A worker crashes on “Pay now”. Kaabist doesn’t press it again. Mark the steps that change something (a submit, a payment, an order) as side effects. Kaabist writes each one down just before it runs and again once it has worked. If a server crashes in between, Kaabist never presses the button again on its own: it pauses and asks you to check. ## Step by step 1. **The program reaches the submit** Steps run one after another. The click on Submit claim is marked as a side effect: it changes something in the world. 2. **The fence goes up** Before it clicks, Kaabist writes the step down as about to execute, outside the browser, where a crash cannot erase it. 3. **The click goes out, and the server dies** The request leaves. Before the confirmation loads, the machine running the job is gone. The portal received the claim; the run never saw it. 4. **Another server takes the job** It replays from the last checkpoint and walks up to the same button. 5. **It finds the fence open, and stops** The step was about to run and never confirmed. Clicking again could file the claim twice, so it does not guess: the run pauses and asks you. 6. **You decide** You check the portal: the claim arrived. You skip the step, and the job carries on after the submit. One claim, filed once. ## Mark the step A side-effect step can be neither retried nor optional, and the linter warns when no checkpoint follows it. That checkpoint is where everything after the submit resumes from. ``` { "click": "#order-form button[type=submit]", "side_effect": true, "expect": { "url": "**/orders/*" } }, { "checkpoint": "order-placed" } ``` ## The fence Before the click, Kaabist writes the step down as about to execute; once its expectation holds, as executed. A server that picks the job up and finds the fence still open does not click. It pauses the job as side_effect_ambiguous and notifies you, so you can check what happened. ## Retries never go back past it A retry can never restart from a checkpoint earlier than the last side effect that ran. Whatever goes wrong after the order is placed, the order is not placed again. ## And no duplicate jobs either Send an Idempotency-Key when you create a job. The same key with the same body within 24 hours returns the original job instead of starting a second one. ``` const idempotencyKey = `order-${orderId}`; const job = await kaab.jobs.create({ program: "place-order", inputs: { sku: "HP-1037", qty: 2 }, idempotencyKey, }); ``` ## Test up to the button A dry run executes the whole flow and stops before the first side effect, so you can test a checkout without buying anything. ## Questions ### What happens after side_effect_ambiguous? You, or the teammate you chose, check the site and decide: skip the step if it went through, or abort the job. Kaabist never guesses. ### Does this replace idempotency on my own side? It complements it. The fence protects the browser step; the Idempotency-Key protects the API call that starts the job. --- # Self-healing locators: The site changed. Your program didn't. Every target is recorded with several ranked locators and a fingerprint of the element it found. When the site changes and they stop matching, Kaabist finds the element again, writes the fix down as a proposal, and lets you promote it to a new version. ## Step by step 1. **A program that worked yesterday** Every morning it opens the portal and clicks Export. Its locator has candidates: a test id, a role and name, the text. 2. **The site is redesigned** Overnight the button moves, its classes are hashed and its label changes. Nobody told you. 3. **The locator misses** None of the candidates matches a single element any more. Instead of guessing, the run stops on that step. 4. **Kaabist finds what moved** It compares the page with the last good snapshot and finds the element that plays the same part: same place in the flow, same job. 5. **It proposes the fix** The new locator comes as a proposal: the diff, the old and new screenshots, and the evidence. Nothing changes on its own. 6. **You approve it** One click promotes it to a new version. The job carries on, and tomorrow's run uses the new locator. ## Candidates, ranked Test ids, roles with names, stable ids, exact text, filtered classes: each target keeps several candidates, tried in order until one matches exactly one element. After the first successful run Kaabist adds more, so every target has at least three. ``` { "click": { "candidates": [ { "testid": "renew" }, { "role": "button", "name": "Renew" }, { "text": "Renew", "exact": true } ] } } ``` ## Deterministic first When every candidate misses, the healer compares the page against the element's fingerprint, then looks for fuzzy anchors such as the text and the shape of the value. A language model is optional, and only ranks or proposes; every candidate is verified against the page. ## Confidence decides A fix scored 0.90 or higher can carry the current job on, and is still recorded as a proposal. Below that, the job pauses as drift, with the evidence, for you to decide. Nothing is promoted to the program without an approval. ## Before your customers notice Canary runs exercise your programs on a schedule, so drift shows up as a proposal before a customer's job fails on it. ``` curl -X POST https://api.kaab.ist/v1/proposals/prp_93Hd/approve \ -H "Authorization: Bearer $KAAB_API_KEY" \ -d '{"promote": true}' ``` ## Questions ### Does healing need an LLM? No. The pipeline is deterministic by default; an LLM is an optional extra step that only proposes candidates, each verified on the page. ### Can a bad fix slip into my program? No. Fixes are proposals. Only an approval promotes one into a new program version, and the old version stays one rollback away. --- # API discovery: The page loads its data from somewhere. Kaabist finds where. On a browser run, Kaabist watches the network for the JSON response that carries the values you extract. Once it has verified that endpoint, later runs read it directly on the HTTP tier: faster, and cheaper in credits. ## Step by step 1. **A browser run reads the page** The program loads the product page in a browser and reads the prices from the screen. A browser run costs five credits. 2. **Behind the page, requests fly** While the page loads, Kaabist watches the JSON responses it receives from its own server. 3. **One of them carries the data** The prices on the screen came from an API call. Kaabist notices the same values in its response. 4. **It checks that they match** Field by field, a validation run checks the response against what the page showed before the endpoint is used. 5. **The next run skips the browser** Later runs read the endpoint directly over plain HTTP: no browser, no rendering, faster. 6. **Same data, a fifth of the cost** The result has the same fields and types. An HTTP request costs one credit instead of five. ## Watch, match, verify The network log of a browser run is scanned for JSON responses whose payload holds the values the program extracted. A match is checked with a validation pass before it is trusted. ## The cheaper tier, automatically A verified endpoint becomes one more locator candidate for that site. When it answers, the next jobs run on the HTTP tier instead of a full browser. ``` { "extract": { "plan": ".plan-name", "renewal_date": { "selector": ".renews", "type": "date" } } } ``` ## Without changing your program You keep writing the program against the page. The endpoint Kaabist found is kept with the site, not in your program, so there is nothing extra to write or maintain. ## Questions ### Does it work on every site? On sites whose pages load their data as JSON, which many modern ones do. When there is no such endpoint, the program simply keeps running in the browser. --- # Sessions and schedules: Log in once. Hear only about what changed. A session keeps a site's login between jobs, so later runs skip straight past it. A schedule runs a program on a cron, compares each result with the last, and sends an event only when the data actually changed. ## Save the session after login A checkpoint can save the browser's session under a name. A program that resumes from that session starts at the checkpoint after the login whenever the session is still valid, and logs in again when it is not. ``` { "options": { "session": "acme", "resume_from_session": true }, "steps": [ { "goto": "https://portal.example.test/login" }, …, { "checkpoint": { "name": "logged_in", "save_session": "acme" } }, { "extract": { "plan": ".plan-name" } } ] } ``` ## Schedules with a timezone A schedule is a program, its inputs and a cron in an IANA timezone. Daylight saving is handled, overlapping runs are skipped, and missed runs are not replayed unless you ask. ``` curl -X POST https://api.kaab.ist/v1/schedules \ -H "Authorization: Bearer $KAAB_API_KEY" \ -d '{ "program": "plan-watch", "cron": "0 9 * * *", "timezone": "Europe/Istanbul", "change_detection": { "enabled": true, "fields": ["plan", "price"] } }' ``` ## Only what changed Each successful run's data, limited to the fields you name, is compared with the previous run's. When it differs you get a schedule.changed event with the changed paths and a JSON Patch of the difference. ## Questions ### What happens when credits run out? Schedules pause instead of failing, and pick up again once there are credits to run on. --- # API discovery (video, 0:44) On a browser run, Kaabist watches the network for the JSON response that carries the values you extract. Once it has verified that endpoint, later runs read it directly on the HTTP tier: faster, and cheaper in credits. The page: [API discovery](https://kaab.ist/product/api-discovery) ## Key moments - 0:02 A browser run reads the page - 0:10 Behind the page, requests fly - 0:16 One of them carries the data - 0:22 It checks that they match - 0:29 The next run skips the browser - 0:35 Same data, a fifth of the cost ## Transcript A browser run reads the page. The program loads the product page in a browser and reads the prices from the screen. A browser run costs five credits. Behind the page, requests fly. While the page loads, Kaabist watches the JSON responses it receives from its own server. One of them carries the data. The prices on the screen came from an API call. Kaabist notices the same values in its response. It checks that they match. Field by field, a validation run checks the response against what the page showed before the endpoint is used. The next run skips the browser. Later runs read the endpoint directly over plain HTTP: no browser, no rendering, faster. Same data, a fifth of the cost. The result has the same fields and types. An HTTP request costs one credit instead of five. --- # Answer a job from a link (video, 0:24) A job logging in parks on a one-time code. The person with the phone opens a hosted page from a link, with no account, types the code, and the job continues from its checkpoint to the report. The page: [Resumes where it stopped](https://kaab.ist/product/resume) ## Key moments - 0:00 The job asks for a code - 0:06 A link goes to the right person - 0:12 They type the code - 0:17 The job carries on ## Transcript The job asks for a code. The site sent a one-time code. The job parks right there, awaiting input, with its browser kept. A link goes to the right person. Whoever has the phone opens a hosted page. No account, no panel: only the question. They type the code. The answer goes to the job, and nowhere else. The job carries on. It continues from its checkpoint, past the login, to the report. Nothing started over. --- # Built by your coding agent (video, 0:45) Connect Claude Code, Codex or Cursor to mcp.kaab.ist. Your agent opens a real Kaabist browser, works through the site with you, and what it does becomes a program: versioned, linted, and tested with a dry run before it ever submits anything. The page: [Built by your coding agent](https://kaab.ist/product/mcp) ## Key moments - 0:02 You ask your agent - 0:08 It opens a real browser - 0:15 It acts on the page - 0:21 It tries the extraction - 0:27 What it did becomes a program - 0:33 Tested, then published ## Transcript You ask your agent. In Claude Code, Codex or Cursor, you describe what you need from a site, in plain words. It opens a real browser. Over MCP, the agent opens a Kaabist browser and reads the page as a view with ranked locators, not as pixels. It acts on the page. It fills, clicks and waits like a person would, and clears whatever covers the page first. It tries the extraction. Fields are tried on the live page, so the agent sees real values before anything is saved. What it did becomes a program. The session turns into a versioned program: the steps, the locators with their fallbacks, the typed fields. Tested, then published. It is linted and tested as a dry run, then pushed. From now on it runs without the agent, on a schedule or a call. --- # Take over a stuck job (video, 0:32) A job parks behind a dialog no rule can close. Someone takes over its live browser in the panel, closes the dialog by hand, and hands the job back; what they did is proposed as new steps for the program. The page: [Resumes where it stopped](https://kaab.ist/product/resume) ## Key moments - 0:00 A job is stuck - 0:07 Take over its browser - 0:13 Close it by hand - 0:17 Hand the job back - 0:22 Your clicks become a proposal ## Transcript A job is stuck. A dialog covers the page, and the program may not hide it. The job parks and waits for a person. Take over its browser. From the attention inbox, open the job's live browser: the real session, where it stopped. Close it by hand. Click the dialog's close button, as on any website. Hand the job back. The job continues from where it stopped, and finishes on its own. Your clicks become a proposal. What you did by hand is proposed as new steps for the program. Nothing changes until you approve it. --- # Review a healed locator (video, 0:31) A site's redesign moved the price, and the program's locator missed it. Kaabist found the element again and proposed the new locator. Review the diff, approve it as version 2, and run it once to be sure. The page: [Self-healing locators](https://kaab.ist/product/self-healing) ## Key moments - 0:00 The site changed - 0:08 Read the diff - 0:13 Approve it as version 2 - 0:19 Run it once ## Transcript The site changed. Overnight the price lost its class. The run found the element again, finished, and wrote the fix down as a proposal. Read the diff. The old locator, the new candidates, and why the element is the same one. Approve it as version 2. Approving publishes a new version. Version 1 stays as it was. Run it once. A canary run of version 2, on the changed site, succeeds. --- # Resumes where it stopped (video, 0:45) Some steps need a person: a one-time code, a captcha, an approval. Kaabist parks the job right there, sends someone a link, and continues the program from its last checkpoint once they answer. Nothing starts over. The page: [Resumes where it stopped](https://kaab.ist/product/resume) ## Key moments - 0:02 The job logs in - 0:08 The site asks for a code - 0:16 A link goes to the right person - 0:23 They type the code - 0:29 The job comes back where it was - 0:36 And carries on ## Transcript The job logs in. The program opens the portal and fills in the email and the password, the way it always does. The site asks for a code. A one-time code goes to someone's phone. The program cannot know it, so the job parks, awaiting input, with its place kept. A link goes to the right person. Kaabist emails a hosted page to the person who has the phone. No account, no dashboard: one field and a button. They type the code. The code goes straight to the waiting job. Nothing else in your system had to change. The job comes back where it was. It continues from its checkpoint, not from the start: the login is not done twice, nothing before it runs again. And carries on. The report is read and returned as typed data. One run, one login, one person asked once. --- # Self-healing locators (video, 0:45) Every target is recorded with several ranked locators and a fingerprint of the element it found. When the site changes and they stop matching, Kaabist finds the element again, writes the fix down as a proposal, and lets you promote it to a new version. ## Key moments - 0:02 A program that worked yesterday - 0:09 The site is redesigned - 0:14 The locator misses - 0:20 Kaabist finds what moved - 0:28 It proposes the fix - 0:35 You approve it ## Transcript A program that worked yesterday. Every morning it opens the portal and clicks Export. Its locator has candidates: a test id, a role and name, the text. The site is redesigned. Overnight the button moves, its classes are hashed and its label changes. Nobody told you. The locator misses. None of the candidates matches a single element any more. Instead of guessing, the run stops on that step. Kaabist finds what moved. It compares the page with the last good snapshot and finds the element that plays the same part: same place in the flow, same job. It proposes the fix. The new locator comes as a proposal: the diff, the old and new screenshots, and the evidence. Nothing changes on its own. You approve it. One click promotes it to a new version. The job carries on, and tomorrow's run uses the new locator. --- # Never submits twice (video, 0:45) Mark the steps that change something, a submit, a payment, an order, as side effects. Kaabist runs each one under a fence: if a run is cut halfway, it never presses the button again on its own. It stops and asks. The page: [Never submits twice](https://kaab.ist/product/side-effects) ## Key moments - 0:02 The program reaches the submit - 0:09 The fence goes up - 0:15 The click goes out, and the worker dies - 0:22 A new worker takes the job - 0:27 It finds the fence open, and stops - 0:34 A person decides ## Transcript The program reaches the submit. Steps run one after another. The click on Submit claim is marked as a side effect: it changes something in the world. The fence goes up. Before it clicks, Kaabist writes the step down as about to execute, outside the browser, where a crash cannot erase it. The click goes out, and the worker dies. The request leaves. Before the confirmation loads, the machine running the job is gone. The portal received the claim; nobody saw it. A new worker takes the job. It replays from the last checkpoint and walks up to the same button. It finds the fence open, and stops. The step was about to run and never confirmed. Clicking again could file the claim twice, so it does not guess: the job parks as side_effect_ambiguous. A person decides. Someone checks the portal: the claim arrived. They skip the step, and the job carries on after the submit. One claim, filed once. --- # The data is behind a login. Log in once, read it every day. Portals, dashboards, supplier sites: the data you need sits behind a sign-in form. Kaabist runs the login as part of a program, keeps the session between jobs, and reads the pages as typed, validated fields. ## The problem Scraping APIs fetch public pages. Behind a login you need a form, a session and sometimes a code, and a scraper that signs in on every single run gets rate-limited, challenged or locked out. ## Log in as part of the program The login is ordinary steps: fill, click, expect. Credentials are inputs given at run time, never written into the program, and password values are redacted wherever a page is recorded. ``` { "goto": "https://portal.example.test/login" }, { "fill": "#email", "value": "{{inputs.email}}" }, { "fill": "#password", "value": "{{inputs.password}}" }, { "click": { "role": "button", "name": "Sign in" }, "expect": { "url": "**/dashboard" } } ``` ## Keep the session Save the session at a checkpoint after the login. The next job that resumes from it goes straight to the data while the session is valid, and signs in again only when it has expired. ``` { "checkpoint": { "name": "logged_in", "save_session": "supplier" } } ``` ## Typed fields, not HTML Extract declares what each field is: money, dates, integers, lists. Values are parsed and validated, and a field that stops filling is noticed before your next run depends on it. ``` { "extract": { "invoice": "h1", "total": { "selector": ".total", "type": "money" }, "due": { "selector": ".due-date", "type": "date" } } } ``` ## When the site adds a step If the portal starts asking for a one-time code, the job pauses on it and Kaabist emails you a link to type the code. The program does not fail, and it does not start over. ## Questions ### Where are the credentials stored? They are inputs of the job or the schedule, stored encrypted and never returned by the API; secret inputs are never shown back. ### What if the session expires mid-week? The program signs in again from the start of its steps, saves the new session, and continues. --- # The site sends a code. You type it. The job goes on. One-time codes by e-mail or SMS, authenticator prompts, approval screens: a second factor is a step only the account owner can finish. Kaabist pauses the job there, emails a link to you (or the teammate or customer who owns the account), and resumes the program the moment the code is typed. ## The problem A headless script cannot read your phone. Teams either switch the second factor off, which security will not accept, or babysit every run, which defeats the automation. ## Wait for the code, in the program await_input names what the job needs and how long it may wait. The value arrives as a variable the next step types in. ``` { "await_input": { "name": "otp", "type": "secret", "collect": "hosted", "hosted": { "notify": "email", "to": "{{inputs.approver}}" } } }, { "fill": "#otp", "value": "{{vars.otp}}" } ``` ## A link, not an account The address you set in the step (yours, a teammate's or your customer's) gets an e-mail with a link to a page on app.kaab.ist. It shows what the job is waiting for and a field for the code. No Kaabist account needed. ## Or answer from your own code If the code reaches a system you control, post it to the job yourself. Subscribe to job.awaiting_input to know when one is needed. ``` curl -X POST https://api.kaab.ist/v1/jobs/job_8KqV2/input \ -H "Authorization: Bearer $KAAB_API_KEY" \ -d '{"otp": "481207"}' ``` ## Ask less often Save the session after the second factor. Later jobs reuse it and skip the whole login, so you are asked for a code only when the session finally expires. ## Questions ### How long can a job wait for the code? As long as the step allows: 24 hours by default, up to 7 days. The browser is not kept open that long; the job resumes from its checkpoint. --- # Orders, payments, applications. Sent once, or not at all. Some forms change the world when they are sent: an order is placed, money moves, an application is filed. Kaabist records those steps just before and just after they run (a fence), so a crash, a retry or a redeploy can never send them twice. ## The problem A script that times out right after clicking Submit cannot know whether the click went through. Retrying may order twice; not retrying may order nothing. Most automation tools simply retry. ## Fence the submit Mark the step as a side effect and follow it with a checkpoint. Kaabist records the fence before the click and closes it once the step's expectation holds. ``` { "click": { "role": "button", "name": "Place order" }, "side_effect": true, "expect": { "url": "**/orders/*" } }, { "checkpoint": "order-placed" } ``` ## A crash pauses, it does not retry When a server finds a fence still open, it does not click again. The job pauses as side_effect_ambiguous with a snapshot and a screenshot, and you check the site and decide. ## One job per order Create each job with an Idempotency-Key. Repeating the call, after a timeout or a deploy, returns the job you already started instead of a second one. ``` curl https://api.kaab.ist/v1/jobs \ -H "Authorization: Bearer $KAAB_API_KEY" \ -H "Idempotency-Key: order-10482" \ -d '{"program": "place-order", "inputs": {"sku": "HP-1037", "qty": 2}}' ``` ## Rehearse without buying Dry runs stop right before the first side effect. Test the whole checkout, with real pages and real validation, without placing an order. ## Questions ### Can I still retry a failed job? Yes, from any checkpoint after the last side effect that ran. A retry cannot go back past a placed order. --- # The site has no API. Your program becomes one. Describe the flow once as a program with inputs. From then on it is one HTTP call: inputs in, typed JSON out, with versions, aliases and webhooks, as if the site had shipped the API itself. ## The problem Partners and old portals rarely offer an API. Wrapping a site in a script works until the next redesign, and then the integration that depends on it breaks without warning. ## A program with inputs Declare the inputs the flow needs. Kaabist validates them on every call, with types, defaults and limits. ``` { "kaab": "1", "name": "plan-lookup", "inputs": { "account": "string" }, "steps": [ … ] } ``` ## One call, typed JSON back Create a job with the program's name and the inputs. With Prefer: wait the response holds up to 30 seconds and returns the finished job with its data. ``` curl https://api.kaab.ist/v1/jobs \ -H "Authorization: Bearer $KAAB_API_KEY" \ -H "Prefer: wait=30" \ -d '{"program": "plan-lookup", "inputs": {"account": "A-1042"}}' ``` ## Versions and aliases Every change is a new version with a diff. Point callers at an alias such as production, and move it when a new version is ready; rolling back is moving it back. ## Faster after the first run When the page loads its data from a JSON endpoint, a browser run finds it and later calls read it directly on the HTTP tier. ## Questions ### What if a call takes longer than 30 seconds? You get the job back while it runs; wait for it with GET /jobs/{id}, or receive job.succeeded on your webhook. --- # Your agent can click through a site. Now it can leave a program behind. Coding agents are good at exploring a site and bad at doing it the same way twice. With Kaabist over MCP, the agent explores in a real browser, and what it learns becomes a fixed program that runs the same way every time, without the agent. ## The problem An agent that drives a browser on every run is slow, costs tokens each time, and takes a slightly different path every time. That is fine for exploring, and wrong for anything you run on a schedule. ## Explore with the agent Connect your agent to mcp.kaab.ist. It opens a Kaabist browser, reads a condensed view of each page, and acts on ranked locators instead of guessing at selectors. ``` claude mcp add --transport http kaab https://mcp.kaab.ist/mcp ``` ## Keep what worked The agent turns its session into a draft program, lints it, and dry-runs it. You review the program, not a transcript. ## Run it without the agent The published program runs on Kaabist, on a schedule or from your API calls, the same way every time. The agent is only needed again when you want to change it. ## Questions ### Does every run cost model tokens? No. Runs execute the program deterministically. A language model is optional and only helps when a locator needs healing. --- # Prices, stock, statuses. Hear only when they change. Watch values that live behind a sign-in: a supplier's price list, a claim's status, an account's limits. Kaabist runs the program on a schedule, compares each result with the last, and calls your webhook only when something changed. ## The problem Polling a page and diffing HTML is noisy: banners, timestamps and layout shifts all look like changes. Behind a login it is worse, because the session keeps expiring between runs. ## Compare fields, not pages Change detection compares the extracted data, limited to the fields you name. A new banner or a reordered menu is not a change; a new price is. ``` { "program": "supplier-prices", "cron": "0 */6 * * *", "timezone": "Europe/Istanbul", "change_detection": { "enabled": true, "fields": ["price", "stock"] } } ``` ## Signed events with the difference A change arrives as schedule.changed with the paths that changed and a link to the JSON Patch between the two runs. Deliveries are signed and retried with backoff; they can also go straight to Slack or Discord. ## The login takes care of itself The program saves its session after signing in and reuses it on the next run. When the session expires, it signs in again; when a code is needed, you get a link to type it in. ## Questions ### What if the site changes its layout? Kaabist finds the moved elements again, or pauses the job with a suggested fix for you to approve, and you hear about it through program.drift_detected, often before a scheduled run fails. --- # Claude Code: Claude Code builds it. Kaabist keeps it running. Add Kaabist to Claude Code with one command. Claude opens a real Kaabist browser, works through the site, and turns what it did into a program you review, test and publish. ## Setup ```sh claude mcp add --transport http kaab https://mcp.kaab.ist/mcp ``` ## Consent, on your terms The first time Claude connects, the Kaabist panel asks you which organisation it works in, test or live mode, what it may do, and how many credits one session may spend: 100 by default. Claude never gets more than your own role. ## Scopes you tick Read, browse and run are on by default. Publishing versions, approving fixes and letting test runs perform side effects are off until you tick them. ``` kaab:read programs, jobs, proposals, usage kaab:browse open browsers you can watch and take over kaab:run save drafts, run test jobs kaab:publish publish versions, move aliases (off) kaab:approve approve fixes (off) kaab:side_effects let test runs submit (off) ``` ## Watch, or take over Every browser Claude opens is listed in the panel. Watch it live, take over yourself when the site needs a human, and revoke the connection from Settings → Connected apps at any time. Guide: https://docs.kaab.ist/guides/mcp --- # Codex: Codex explores the site. A program stays behind. Point Codex at Kaabist's MCP server and it can drive a real browser on Kaabist's pool, read pages through ranked locators, and save what works as a draft program. ## Setup ```sh # ~/.codex/config.toml [mcp_servers.kaab] url = "https://mcp.kaab.ist/mcp" ``` ## Sign in once When Codex first connects, your browser opens Kaabist's consent page. Choose the organisation, the mode and the scopes; Codex works within them and nothing more. ## Draft, lint, dry run Codex turns its browser session into a draft program, lints it and runs it as a dry run that stops before the first side effect. Publishing is a scope you grant, or a click you make yourself. Guide: https://docs.kaab.ist/guides/mcp --- # Cursor: Automate a site without leaving your editor. Add Kaabist to Cursor's MCP servers. The agent in your editor opens Kaabist browsers, tries extracts on the live page, and writes the program next to your code. ## Setup ```sh // .cursor/mcp.json { "mcpServers": { "kaab": { "url": "https://mcp.kaab.ist/mcp" } } } ``` ## Try before you save The agent can try an extract on the page it is looking at and see the typed values before a single step is saved, so the program is right the first time. ## Pull it into your repository Programs are JSON. Keep them in your repository and push them with the CLI from your pipeline, so a change to an automation is reviewed like any other change. ``` kaab programs pull renew-subscription@production -o renew.json kaab programs lint renew.json kaab programs push renew.json --publish ``` Guide: https://docs.kaab.ist/guides/mcp --- # TypeScript SDK: Typed requests. Safe retries. One wait. @kaabist/sdk gives you every API operation as a typed method, retries that never run a job twice, and a wait helper that can answer a job's questions as it goes. ## Setup ```sh npm install @kaabist/sdk ``` ## Run a job Create a job and hold the request open for its result. The client reads KAAB_API_KEY from the environment. ``` import { Kaab } from "@kaabist/sdk"; const kaab = new Kaab(); const job = await kaab.jobs.create({ program: "renew-subscription@production", inputs: { account: "A-1042" }, wait: 30, }); ``` ## Wait, and answer jobs.wait long-polls until the job ends. Give it onInput to supply a one-time code the job asks for, and onAttention to decide what to do when it needs attention. ## Retries that cannot run twice jobs.create always sends an Idempotency-Key, so a retried create returns the same job. Pass your own key to make your retries safe too. Guide: https://docs.kaab.ist/guides/sdks --- # Python SDK: Blocking or asyncio. Fully typed. The kaabist package covers the whole API for Python 3.11 and later, with typed models, pages that fetch as you iterate, and a wait that can answer a job's questions as it goes. ## Setup ```sh pip install kaabist ``` ## Run and wait Create a job, then wait for it. on_input supplies a value the job asked for; on_attention decides what happens when it needs attention. ``` from kaabist import Kaab with Kaab() as kaab: # KAAB_API_KEY job = kaab.jobs.create(program="renew-subscription@production", inputs={"account": "A-1042"}) done = kaab.jobs.wait( job.id, on_input=lambda request, job: ask_for_code(request.prompt), ) ``` ## Async, the same way AsyncKaab has the same methods for asyncio code, and lists iterate across pages as you go. ``` from kaabist import AsyncKaab async with AsyncKaab() as kaab: async for proposal in kaab.proposals.list(status="pending"): print(proposal.id) ``` Guide: https://docs.kaab.ist/guides/sdks --- # Go SDK: The same API, the Go way. github.com/kaabist/kaab-go gives Go services the full API with typed errors, retries with idempotency keys, and iterators over every list. ## Setup ```sh go get github.com/kaabist/kaab-go ``` ## Same names, every language Every operation is a resource and a method, named the same in Go, TypeScript and Python, so examples translate one to one. ## Lists as iterators List calls iterate across pages for you, with an error per item, in a plain range loop. Guide: https://docs.kaab.ist/guides/sdks --- # kaab CLI: Jobs, programs, schedules from your terminal. The kaab command runs jobs, pushes and pulls programs, approves proposals and creates schedules. It fits in scripts and pipelines: exit codes say what happened. ## Setup ```sh go install github.com/kaabist/kaab-go/cmd/kaab@latest kaab auth login ``` ## Run a job Run a program with inputs and a session, and wait for the result. The data goes to standard output. ``` kaab jobs run --program acme-report@production \ --input report_id=42 --session acme --wait 60 > data.json ``` ## Programs as files Lint, push, pull and diff programs like code, and review fixes from the terminal. ``` kaab programs lint report.json kaab programs push report.json --publish kaab programs diff acme-report 3 4 kaab proposals approve prp_93Hd --promote ``` ## Schedules and webhooks Set up a schedule with change detection and a webhook in two lines. ``` kaab schedules create --program acme-report@production \ --cron "0 * * * *" --change-detection --field price kaab webhooks create --url https://example.com/hooks --events 'job.*' ``` Guide: https://docs.kaab.ist/guides/cli --- # Webhooks: Hear about it the moment it happens. Kaabist sends signed events to your endpoints: jobs that finish, wait for input or need attention, schedules that found a change, programs that drifted. Deliveries are retried with backoff and can go straight to Slack or Discord. ## Setup ```sh kaab webhooks create --url https://example.com/hooks --events 'job.*' ``` ## Signed, every time Every delivery carries a Kaab-Signature header: a timestamp and an HMAC-SHA256 of the raw body. Verify it on the bytes as they arrived; the SDKs do it in one call. ``` Kaab-Signature: t=1758362400,v1=5257a869e7ec… webhooks.verify(rawBody, signatureHeader, secret) // in every SDK ``` ## Retried until it lands A failed delivery is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours. Every attempt is in the event log, and you can resend any of them. ## Pick what you hear Subscribe to exact events or whole groups: job.succeeded, job.awaiting_input, job.needs_attention, schedule.changed, proposal.created, program.drift_detected, credits.low and more. Guide: https://docs.kaab.ist/guides/webhooks --- # Kaabist vs Airtop Airtop compiles described workflows into deterministic agents that run on schedules and heal through drafts you review and deploy. Kaabist shares the reviewable-healing approach and adds a pause mid-run that waits for your answer and continues from the last checkpoint, guards that record a submit before and after it runs so it never runs twice, an MCP server for coding agents, and API discovery. Airtop, in their words: "Deploy agents that automate every part of your business." (https://www.airtop.ai) Airtop pricing: Free plan with 1,000 credits; Starter from $29/month; Professional from $189/month; Enterprise from $558/month; custom plans on request. Source: https://www.airtop.ai/pricing ## Capabilities | Capability | Kaabist | Airtop | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Agent Builder turns a described workflow into an agent that visits sites, collects data and sends it to connected apps. https://www.airtop.ai/help/guides/agent-builder.md | | Persistent sessions | yes | yes | Each agent has a managed browser profile that stores session cookies and reuses them in background runs. https://www.airtop.ai/help/guides/authentication.md | | Self-healing locators, delivered as proposals you review | yes | yes | Repairs are prepared and tested as a draft that you inspect and deploy; agents pause after 3 consecutive failures by default. https://www.airtop.ai/help/guides/self-healing.md | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | You sign in or complete 2FA in a live browser while setting up an agent; we found no mid-run pause that waits for your answer and continues. https://www.airtop.ai/help/guides/authentication.md | | A submit or payment never runs twice, even after a crash | yes | no | No mechanism to keep a step from running twice after a crash or retry is documented. https://www.airtop.ai/help/guides/FAQ.md | | A coding agent builds the program over MCP | yes | no | The docs offer an MCP endpoint for searching documentation; we found no first-party MCP server for running agents or browsers. https://docs.airtop.ai/llms.txt | | Schedules and change detection | yes | yes | Agents run on schedules or triggers, and an agent can watch a page for a change and act when it happens. https://www.airtop.ai | ## When to choose Airtop You want to describe a business workflow in plain language and get a scheduled agent with reviewed repairs and app integrations, without writing or reading program code. By Kaabist. Last verified 10 October 2026 against Airtop's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Anchor Browser Anchor Browser is close to Kaabist in spirit: deterministic tasks that heal as reviewable drafts. Where they differ is what happens when a flow needs you and around a submit: any Kaabist program can pause at its last checkpoint until you answer, and every step that must not run twice is guarded. Anchor Browser, in their words: "Computer Environments for AI Agents" (https://anchorbrowser.io) Anchor Browser pricing: Free plan with 5 credits; Starter $50/month. Source: https://anchorbrowser.io/pricing ## Capabilities | Capability | Kaabist | Anchor Browser | Note and source | |---|---|---|---| | Self-healing locators, delivered as proposals you review | yes | yes | A healed task becomes a draft version you review as a diff, test and publish. https://docs.anchorbrowser.io/advanced/self-healing.md | | Logged-in, multi-step flows | yes | yes | Automation tasks compiled from a prompt or a demonstration, with a hosted login page. https://docs.anchorbrowser.io | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | Agent tasks can pause for you to step in through a takeover link; we found no checkpoint resume for deterministic tasks. https://docs.anchorbrowser.io | | A submit or payment never runs twice, even after a crash | yes | no | No mechanism to keep a step from running twice after a crash. https://docs.anchorbrowser.io | | A coding agent builds the program over MCP | yes | yes | MCP support for agents. https://docs.anchorbrowser.io | ## When to choose Anchor Browser You want AI-built browser tasks with reviewable healing on Anchor's environments, and your flows rarely need your input mid-run or a guarded submit. By Kaabist. Last verified 10 October 2026 against Anchor Browser's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Apify Apify is a platform and marketplace for running scrapers and automation tools called Actors, which you pick from its store or write yourself. Kaabist runs your own fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guard every step that submits so it runs once, heal through fixes you review, and discover a site's APIs to skip the browser. Apify, in their words: "Apify is a marketplace of ready-to-run tools for AI that automate work on the web." (https://apify.com) Apify pricing: Free plan with $5 monthly usage; Starter $19/month; Scale $199/month; Business $999/month; compute units cost $0.13 to $0.20 depending on plan. Source: https://apify.com/pricing ## Capabilities | Capability | Kaabist | Apify | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Actors are programs you write with Playwright or Puppeteer, or ready-made tools from Apify Store, so any multi-step flow can be coded. https://docs.apify.com/academy/puppeteer-playwright/common-use-cases/logging-into-a-website.md | | Persistent sessions | yes | partial | Logged-in state is reused through cookies handled in your Actor code; we found no managed login store shared across runs. https://docs.apify.com/academy/puppeteer-playwright/common-use-cases/logging-into-a-website.md | | Self-healing locators, delivered as proposals you review | yes | no | Store Actors are tested daily and labeled under maintenance when they fail; the developer fixes and rebuilds them. https://docs.apify.com/actors/publishing/test.md | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | no | No built-in way for a run to wait for your input and continue; Actors can persist their own state to survive server migrations. https://docs.apify.com/actors/running.md | | A submit or payment never runs twice, even after a crash | yes | no | State persistence is opt-in developer code; no platform mechanism keeps a side-effecting step from running twice after a restart. https://docs.apify.com/actors/development/builds-and-runs/state-persistence.md | | A coding agent builds the program over MCP | yes | yes | A hosted MCP server at mcp.apify.com with OAuth lets agents search, run and read Actors and their storage. https://docs.apify.com/mcp.md | | Schedules and change detection | yes | partial | Actors and tasks run on cron schedules with timezones; comparing results between runs is left to your Actor or downstream code. https://docs.apify.com/actors/running/schedules.md | ## When to choose Apify A ready-made Actor in Apify Store already covers the site you need, or you want to run your own Crawlee, Playwright or Puppeteer code on a mature hosted platform. By Kaabist. Last verified 10 October 2026 against Apify's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Browser Use Browser Use runs AI agents that complete browser tasks from a prompt, plus remote browsers for your own agents. Kaabist runs fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guards every step that submits so it never runs twice, delivers healing as fixes you review, and discovers a site's APIs. Browser Use, in their words: "Agents that use the browser." (https://browser-use.com) Browser Use pricing: Pay as you go with no subscription: browsers $0.02/hour, residential proxy $5/GB, agents at model cost plus 20%, $5 minimum top-up. Source: https://browser-use.com/pricing ## Capabilities | Capability | Kaabist | Browser Use | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | An AI agent carries out multi-step browser tasks from a prompt and can save a working script to rerun later. https://docs.browser-use.com/cloud/agent/scripts.md | | Persistent sessions | yes | yes | Profiles persist cookies, local storage and login state so later browsers start logged in. https://docs.browser-use.com/cloud/guides/authentication.md | | Self-healing locators, delivered as proposals you review | yes | partial | The agent can be told to repair a saved script that fails during a run; we found no review step or version diff. https://docs.browser-use.com/cloud/agent/scripts.md | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | After a run ends, you take over through the live browser, then a new follow-up run continues in the same session. https://docs.browser-use.com/cloud/agent/human-in-the-loop.md | | A submit or payment never runs twice, even after a crash | yes | no | The docs advise reconciling external actions yourself before retrying; no mechanism keeps a step from running twice. https://docs.browser-use.com/cloud/guides/troubleshooting.md | | A coding agent builds the program over MCP | yes | yes | A hosted MCP server lets coding assistants run tasks, send follow-ups and use browser profiles. https://docs.browser-use.com/cloud/guides/mcp-server.md | | Schedules and change detection | yes | unclear | A showcase page describes scheduled tasks, but we found no scheduling page in the current Cloud documentation. https://browser-use.com/showcase/schedule-daily-browser-task | ## When to choose Browser Use You want an open-source or hosted agent that handles open-ended browser tasks from a prompt, with usage-based pricing and no subscription. By Kaabist. Last verified 10 October 2026 against Browser Use's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Browser Use Browser Use runs AI agents that complete browser tasks from a prompt, plus remote browsers for your own agents. Kaabist runs fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guards every step that submits so it never runs twice, delivers healing as fixes you review, and discovers a site's APIs. Browser Use, in their words: "Agents that use the browser." (https://browser-use.com) Browser Use pricing: Pay as you go with no subscription: browsers $0.02/hour, residential proxy $5/GB, agents at model cost plus 20%, $5 minimum top-up. Source: https://browser-use.com/pricing ## Capabilities | Capability | Kaabist | Browser Use | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | An AI agent carries out multi-step browser tasks from a prompt and can save a working script to rerun later. https://docs.browser-use.com/cloud/agent/scripts.md | | Persistent sessions | yes | yes | Profiles persist cookies, local storage and login state so later browsers start logged in. https://docs.browser-use.com/cloud/guides/authentication.md | | Self-healing locators, delivered as proposals you review | yes | partial | The agent can be told to repair a saved script that fails during a run; we found no review step or version diff. https://docs.browser-use.com/cloud/agent/scripts.md | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | After a run ends, you take over through the live browser, then a new follow-up run continues in the same session. https://docs.browser-use.com/cloud/agent/human-in-the-loop.md | | A submit or payment never runs twice, even after a crash | yes | no | The docs advise reconciling external actions yourself before retrying; no mechanism keeps a step from running twice. https://docs.browser-use.com/cloud/guides/troubleshooting.md | | A coding agent builds the program over MCP | yes | yes | A hosted MCP server lets coding assistants run tasks, send follow-ups and use browser profiles. https://docs.browser-use.com/cloud/guides/mcp-server.md | | Schedules and change detection | yes | unclear | A showcase page describes scheduled tasks, but we found no scheduling page in the current Cloud documentation. https://browser-use.com/showcase/schedule-daily-browser-task | ## When to choose Browser Use You want an open-source or hosted agent that handles open-ended browser tasks from a prompt, with usage-based pricing and no subscription. By Kaabist. Last verified 10 October 2026 against Browser Use's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Browserbase Browserbase is browser infrastructure: remote browsers for your code, and Stagehand for AI actions inside it. Kaabist runs whole programs on its own browsers: it pauses them when a site needs you, resumes them from their last checkpoint once you answer, and guards every step that submits. Browserbase, in their words: "Give your agents access to the whole web." (https://www.browserbase.com) Browserbase pricing: Free plan with 1 browser-hour; Developer $20/month for 100 browser-hours; Startup $99/month for 500. Source: https://www.browserbase.com/pricing ## Capabilities | Capability | Kaabist | Browserbase | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Remote browsers for your own Playwright or Puppeteer code, and Stagehand for AI-driven actions. https://docs.browserbase.com | | Persistent sessions | yes | yes | Sessions and contexts persist cookies between runs. https://docs.browserbase.com | | Self-healing locators, delivered as proposals you review | yes | partial | When a cached Stagehand step stops matching, the model runs the action again and the cache is rewritten, without a review step. https://browserbase.com/blog/stagehand-caching | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | An interactive Live View lets you take control of a running session; we found no checkpoint a paused program resumes from. https://docs.browserbase.com | | A submit or payment never runs twice, even after a crash | yes | no | No mechanism to keep a step from running twice after a crash. https://docs.browserbase.com | | A coding agent builds the program over MCP | yes | yes | An MCP server lets agents drive Browserbase browsers. https://docs.browserbase.com | | Schedules and change detection | yes | partial | Director can run tasks on a schedule; no field-level change detection found. https://www.browserbase.com | ## When to choose Browserbase You already have Playwright, Puppeteer or Stagehand code and want reliable, scalable remote browsers to run it on, with your own logic around every step. By Kaabist. Last verified 10 October 2026 against Browserbase's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Browserbase Browserbase is browser infrastructure: remote browsers for your code, and Stagehand for AI actions inside it. Kaabist runs whole programs on its own browsers: it pauses them when a site needs you, resumes them from their last checkpoint once you answer, and guards every step that submits. Browserbase, in their words: "Give your agents access to the whole web." (https://www.browserbase.com) Browserbase pricing: Free plan with 1 browser-hour; Developer $20/month for 100 browser-hours; Startup $99/month for 500. Source: https://www.browserbase.com/pricing ## Capabilities | Capability | Kaabist | Browserbase | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Remote browsers for your own Playwright or Puppeteer code, and Stagehand for AI-driven actions. https://docs.browserbase.com | | Persistent sessions | yes | yes | Sessions and contexts persist cookies between runs. https://docs.browserbase.com | | Self-healing locators, delivered as proposals you review | yes | partial | When a cached Stagehand step stops matching, the model runs the action again and the cache is rewritten, without a review step. https://browserbase.com/blog/stagehand-caching | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | An interactive Live View lets you take control of a running session; we found no checkpoint a paused program resumes from. https://docs.browserbase.com | | A submit or payment never runs twice, even after a crash | yes | no | No mechanism to keep a step from running twice after a crash. https://docs.browserbase.com | | A coding agent builds the program over MCP | yes | yes | An MCP server lets agents drive Browserbase browsers. https://docs.browserbase.com | | Schedules and change detection | yes | partial | Director can run tasks on a schedule; no field-level change detection found. https://www.browserbase.com | ## When to choose Browserbase You already have Playwright, Puppeteer or Stagehand code and want reliable, scalable remote browsers to run it on, with your own logic around every step. By Kaabist. Last verified 10 October 2026 against Browserbase's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Browserless Browserless runs browsers for your code and hands a session to you well: a live link with a done button. Kaabist takes the step further: the program itself pauses until you answer, resumes from its last checkpoint, heals its locators, and never repeats a submit. Browserless, in their words: "The web layer your agents run on" (https://www.browserless.io) Browserless pricing: Free 1k units; Prototyping $25/month for 20k units; Starter $140/month for 180k. A unit is 30 seconds of browser time. Source: https://www.browserless.io/pricing ## Capabilities | Capability | Kaabist | Browserless | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Browsers as a service for any CDP client, plus BrowserQL, their own query language. https://docs.browserless.io | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | A hosted live URL lets you act in the session and tell the script to continue; the script itself handles the rest. https://docs.browserless.io/baas/interactive-browser-sessions/hybrid-automation | | Persistent sessions | yes | yes | Persistent sessions and reconnects. https://docs.browserless.io | | Self-healing locators, delivered as proposals you review | yes | no | No locator healing found. https://docs.browserless.io | | A submit or payment never runs twice, even after a crash | yes | no | No mechanism to keep a step from running twice after a crash. https://docs.browserless.io | | A coding agent builds the program over MCP | yes | yes | A hosted MCP server for agents. https://docs.browserless.io | ## When to choose Browserless You want browsers as a service for existing CDP code, or BrowserQL, and you are happy to write the waiting, retrying and recovering logic around them yourself. By Kaabist. Last verified 10 October 2026 against Browserless's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Firecrawl Firecrawl turns pages into clean markdown or JSON for models, fast and at scale. Kaabist is for the flows around the data: logging in, waiting for your 2FA code, submitting once, and keeping that program working when the site changes. Firecrawl, in their words: "Give your agents web data and beyond" (https://www.firecrawl.dev) Firecrawl pricing: Free 1,000 credits; Hobby $19/month for 5,000; one credit per page, four more for JSON extraction. Source: https://www.firecrawl.dev/pricing ## Capabilities | Capability | Kaabist | Firecrawl | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Actions (click, write, wait) before a scrape, and profiles that keep a login. https://docs.firecrawl.dev/features/interact | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | An interactive live view lets you type into the session; no paused program resumes from a checkpoint. https://docs.firecrawl.dev/features/interact | | Schedules and change detection | yes | yes | Monitor re-checks pages on a schedule and reports diffs. https://docs.firecrawl.dev | | Signed webhooks | yes | yes | Signed webhooks. https://docs.firecrawl.dev | | A coding agent builds the program over MCP | yes | yes | An official MCP server. https://docs.firecrawl.dev | | A submit or payment never runs twice, even after a crash | yes | no | Built for reading pages; no mechanism for steps that must submit once. https://docs.firecrawl.dev | | Self-healing locators, delivered as proposals you review | yes | unclear | Monitor promises stable field extraction; we found nothing on what happens when the page is redesigned. | ## When to choose Firecrawl You mostly read public pages, crawl or search the web for an LLM, and want markdown or schema-shaped JSON with as little setup as possible. By Kaabist. Last verified 10 October 2026 against Firecrawl's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Firecrawl Firecrawl turns pages into clean markdown or JSON for models, fast and at scale. Kaabist is for the flows around the data: logging in, waiting for your 2FA code, submitting once, and keeping that program working when the site changes. Firecrawl, in their words: "Give your agents web data and beyond" (https://www.firecrawl.dev) Firecrawl pricing: Free 1,000 credits; Hobby $19/month for 5,000; one credit per page, four more for JSON extraction. Source: https://www.firecrawl.dev/pricing ## Capabilities | Capability | Kaabist | Firecrawl | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Actions (click, write, wait) before a scrape, and profiles that keep a login. https://docs.firecrawl.dev/features/interact | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | An interactive live view lets you type into the session; no paused program resumes from a checkpoint. https://docs.firecrawl.dev/features/interact | | Schedules and change detection | yes | yes | Monitor re-checks pages on a schedule and reports diffs. https://docs.firecrawl.dev | | Signed webhooks | yes | yes | Signed webhooks. https://docs.firecrawl.dev | | A coding agent builds the program over MCP | yes | yes | An official MCP server. https://docs.firecrawl.dev | | A submit or payment never runs twice, even after a crash | yes | no | Built for reading pages; no mechanism for steps that must submit once. https://docs.firecrawl.dev | | Self-healing locators, delivered as proposals you review | yes | unclear | Monitor promises stable field extraction; we found nothing on what happens when the page is redesigned. | ## When to choose Firecrawl You mostly read public pages, crawl or search the web for an LLM, and want markdown or schema-shaped JSON with as little setup as possible. By Kaabist. Last verified 10 October 2026 against Firecrawl's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Playwright, by hand Playwright is the engine under a great deal of browser automation, Kaabist's included. Writing it by hand gives you total control and every operational problem: logins that expire, selectors that break, a 2FA code someone has to type at the keyboard, a retry that submits twice. Playwright, by hand, in their words: "Playwright enables reliable end-to-end testing for modern web apps." (https://playwright.dev) Playwright, by hand pricing: Free and open source. You run the browsers, the scheduling and the recovery yourself. Source: https://playwright.dev ## Capabilities | Capability | Kaabist | Playwright, by hand | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Anything a browser can do, in code you write and maintain. https://playwright.dev/docs/auth | | Persistent sessions | yes | yes | Storage state saves a login for reuse. https://playwright.dev/docs/auth | | Self-healing locators, delivered as proposals you review | yes | no | Locators are what you wrote; when the page changes, the script fails until you fix it. https://playwright.dev/docs/locators | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | no | No built-in way to pause a run for your input and resume it hours later. https://playwright.dev/docs/intro | | A submit or payment never runs twice, even after a crash | yes | no | A retry runs the whole script again, submit included. https://playwright.dev/docs/intro | | A coding agent builds the program over MCP | yes | partial | Playwright MCP lets an agent drive a browser; it does not leave a program behind. https://github.com/microsoft/playwright-mcp | | Schedules and change detection | yes | no | Scheduling, change detection and alerts are yours to build. https://playwright.dev/docs/intro | ## When to choose Playwright, by hand The flow is simple, rarely changes, never needs your input in the middle, and you would rather own every line than run it as a service. By Kaabist. Last verified 10 October 2026 against Playwright, by hand's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Scrape.do Scrape.do is a scraping API that fetches pages through rotating datacenter, residential or mobile proxies, optionally in a headless browser with a list of actions, and charges only for successful requests. Kaabist runs fixed programs that pause when a site needs you and continue from their last checkpoint once you answer, guard every step that submits so it runs once, heal through fixes you review, work with coding agents over MCP, and discover a site's APIs to skip the browser. Scrape.do, in their words: "Reliable, Scalable, Unstoppable Web Scraping" (https://scrape.do) Scrape.do pricing: Free plan with 1,000 credits; Hobby $29/month for 250,000 credits; Pro $99/month for 1.25 million; Business $249/month for 3.5 million; Advanced $699/month for 10 million; only successful requests use credits. Source: https://scrape.do/pricing/ ## Capabilities | Capability | Kaabist | Scrape.do | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | partial | The playWithBrowser parameter runs an ordered list of actions such as Click, Fill, Wait and Execute inside one rendered request; logic across requests lives in your code. https://scrape.do/documentation/headless-browser/browser-interactions/ | | Persistent sessions | yes | partial | A sessionId keeps the same proxy address until 5 minutes without a request, and cookies are passed with each request through setCookies; we found no stored login reused across runs. https://scrape.do/documentation/api-response/session-id.md | | Self-healing locators, delivered as proposals you review | yes | unclear | The documentation does not describe what happens to your own actions or selectors when a site changes. | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | no | Each request runs its actions and returns per-action results; we found no way for a request to wait for your input and continue. https://scrape.do/documentation/headless-browser/browser-interactions/ | | A submit or payment never runs twice, even after a crash | yes | no | Requests are independent and the FAQ advises retrying failed ones; no mechanism keeps a submitting action from running twice. https://scrape.do/documentation/faq/ | | A coding agent builds the program over MCP | yes | partial | Scrape.do's documentation lists n8n and Zapier integrations but no MCP server; a third-party Composio toolkit exposes the API to MCP clients. https://composio.dev/toolkits/scrape_do/framework/claude-code | | Schedules and change detection | yes | partial | The n8n guide runs scrapes on an n8n Schedule Trigger; we found no built-in scheduler or change detection. https://scrape.do/documentation/integrations/n8n/ | | Signed webhooks | yes | yes | Async API jobs accept a WebhookURL so results arrive without polling. https://scrape.do/documentation/async-api/ | ## When to choose Scrape.do You need large volumes of pages fetched past anti-bot systems at a per-request price, and the parsing and logic between requests already live in your own code. By Kaabist. Last verified 10 October 2026 against Scrape.do's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Skyvern Skyvern is an AI agent platform that runs browser workflows and caches successful runs as code that is regenerated by the agent when a page changes. Kaabist runs fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guards every step that submits so it never runs twice, delivers healing as fixes you review, and discovers a site's APIs. Skyvern, in their words: "AI agents to automate workflows on any website." (https://www.skyvern.com) Skyvern pricing: Free plan with 5,000 one-time credits; Hobby $29/month for 30,000 credits; Pro $149/month for 150,000 credits; Enterprise custom. Source: https://www.skyvern.com/pricing ## Capabilities | Capability | Kaabist | Skyvern | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Workflows chain blocks for login, navigation, actions and extraction, and later blocks can use earlier outputs. https://www.skyvern.com/docs/developers/getting-started/core-concepts.md | | Persistent sessions | yes | yes | Browser profiles save cookies and localStorage so later runs start logged in; a credential vault handles passwords and TOTP. https://www.skyvern.com/docs/developers/optimization/browser-profiles.md | | Self-healing locators, delivered as proposals you review | yes | partial | When cached code fails because a page changed, Skyvern falls back to the agent and regenerates the cache automatically; we found no review step. https://www.skyvern.com/docs/developers/features/code-caching.md | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | A Human Interaction block pauses a workflow for approve or reject and auto-continues after a timeout; human-in-the-loop is listed on the Enterprise plan. https://www.skyvern.com/docs/cloud/building-workflows/configure-blocks.md | | A submit or payment never runs twice, even after a crash | yes | no | The error-handling docs describe retries but no mechanism to keep a submit step from running twice after a crash or retry. https://www.skyvern.com/docs/developers/going-to-production/error-handling.md | | A coding agent builds the program over MCP | yes | yes | Hosted and self-hosted MCP servers with 75+ tools for browser sessions, actions, credentials and workflows. https://www.skyvern.com/docs/developers/getting-started/mcp.md | | Schedules and change detection | yes | partial | Workflows run on cron schedules with a timezone and a 5-minute minimum; we found no change detection between runs. https://www.skyvern.com/docs/cloud/building-agents/scheduling.md | ## When to choose Skyvern You want an AI agent to build and run browser workflows from natural-language goals, with built-in credential and TOTP handling, and automatic cache regeneration suits you. By Kaabist. Last verified 10 October 2026 against Skyvern's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # Kaabist vs Skyvern Skyvern is an AI agent platform that runs browser workflows and caches successful runs as code that is regenerated by the agent when a page changes. Kaabist runs fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guards every step that submits so it never runs twice, delivers healing as fixes you review, and discovers a site's APIs. Skyvern, in their words: "AI agents to automate workflows on any website." (https://www.skyvern.com) Skyvern pricing: Free plan with 5,000 one-time credits; Hobby $29/month for 30,000 credits; Pro $149/month for 150,000 credits; Enterprise custom. Source: https://www.skyvern.com/pricing ## Capabilities | Capability | Kaabist | Skyvern | Note and source | |---|---|---|---| | Logged-in, multi-step flows | yes | yes | Workflows chain blocks for login, navigation, actions and extraction, and later blocks can use earlier outputs. https://www.skyvern.com/docs/developers/getting-started/core-concepts.md | | Persistent sessions | yes | yes | Browser profiles save cookies and localStorage so later runs start logged in; a credential vault handles passwords and TOTP. https://www.skyvern.com/docs/developers/optimization/browser-profiles.md | | Self-healing locators, delivered as proposals you review | yes | partial | When cached code fails because a page changed, Skyvern falls back to the agent and regenerates the cache automatically; we found no review step. https://www.skyvern.com/docs/developers/features/code-caching.md | | Pause for your 2FA code or approval, then continue from the last checkpoint | yes | partial | A Human Interaction block pauses a workflow for approve or reject and auto-continues after a timeout; human-in-the-loop is listed on the Enterprise plan. https://www.skyvern.com/docs/cloud/building-workflows/configure-blocks.md | | A submit or payment never runs twice, even after a crash | yes | no | The error-handling docs describe retries but no mechanism to keep a submit step from running twice after a crash or retry. https://www.skyvern.com/docs/developers/going-to-production/error-handling.md | | A coding agent builds the program over MCP | yes | yes | Hosted and self-hosted MCP servers with 75+ tools for browser sessions, actions, credentials and workflows. https://www.skyvern.com/docs/developers/getting-started/mcp.md | | Schedules and change detection | yes | partial | Workflows run on cron schedules with a timezone and a 5-minute minimum; we found no change detection between runs. https://www.skyvern.com/docs/cloud/building-agents/scheduling.md | ## When to choose Skyvern You want an AI agent to build and run browser workflows from natural-language goals, with built-in credential and TOTP handling, and automatic cache regeneration suits you. By Kaabist. Last verified 10 October 2026 against Skyvern's public documentation. Method: [how we compare](https://kaab.ist/vs#method) --- # API discovery Finding the JSON requests a website makes behind its pages, so data can be read from them instead of from the screen. While a page loads, Kaabist records the JSON responses it receives. A program can read a field straight from one of them, which is faster than reading the page and survives redesigns of the layout. ``` { "extract": { "offers": { "network": { "url": "**/api/offers*", "json": "$.items[*].price" }, "type": "list" } } } ``` ## Related - [API discovery](https://kaab.ist/product/api-discovery) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Tier ladder](https://kaab.ist/glossary/tier-ladder) --- # Await input A step that pauses a job until you, a teammate or your own system supplies a value the program cannot know in advance, such as a one-time code. The job pauses, keeping its browser open for a short time, with a separate deadline for the answer. The value can arrive through the API, through an agent, or through a hosted page that Kaabist emails to the address you choose. The job then continues where it stopped. ``` { "await_input": { "name": "otp", "prompt": "Enter the code sent to {{inputs.email}}", "ttl": "5m", "expires": "24h", "collect": "hosted" } } ``` ## Related - [Resumes where it stopped](https://kaab.ist/product/resume) - [Automate logins with 2FA](https://kaab.ist/use-cases/login-with-2fa) - [Hosted resolve page](https://kaab.ist/glossary/hosted-resolve-page) - [Needs attention](https://kaab.ist/glossary/needs-attention) --- # Browser session A saved, named login state (cookies and storage) that jobs reuse so they do not log in every time. Bind a session with the session option and Kaabist checks it is still valid before the job starts. If it expired, the program signs in again with the stored login inputs, pauses for you to step in, or fails, as its policy says. ``` { "kaab": "1", "name": "acme-report", "options": { "session": "acme", "resume_from_session": true }, "policies": { "on_session_expired": "refresh" }, "steps": [ "…" ] } ``` ## Related - [Sessions and schedules](https://kaab.ist/product/sessions-and-schedules) - [Resumes where it stopped](https://kaab.ist/product/resume) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login) - [Checkpoint](https://kaab.ist/glossary/checkpoint) --- # Canary run A scheduled test run of a program that checks it still works on the live site before your real jobs find out it does not. Programs in use get canary runs every few hours. When one fails because the site changed, Kaabist diagnoses the change and prepares a fix while your production jobs are still unaffected. ``` { "options": { "canary": { "enabled": true, "cron": "0 */6 * * *", "url": "https://shop.example.com/p/123" } } } ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Drift](https://kaab.ist/glossary/drift) - [Proposal](https://kaab.ist/glossary/proposal) --- # Captcha policy What a program does when a site asks it to prove it is human: pause and wait for you, solve it, or fail. The default is to pause the job (park) and let you decide. A program can opt into solving it through the platform's solver or your own. ``` { "policies": { "captcha": "park" } } ``` ## Related - [Resumes where it stopped](https://kaab.ist/product/resume) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Needs attention](https://kaab.ist/glossary/needs-attention) - [Takeover](https://kaab.ist/glossary/takeover) --- # Change detection Running a program on a schedule and being told only when the fields you care about change. A schedule with change detection compares each run's data with the last run's, field by field, and sends a schedule.changed event with the difference. Unchanged runs stay quiet. ``` kaab schedules create --program acme-report@production \ --cron "0 * * * *" --change-detection --field price ``` ## Related - [Sessions and schedules](https://kaab.ist/product/sessions-and-schedules) - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login) - [Browser session](https://kaab.ist/glossary/browser-session) - [Webhook signature](https://kaab.ist/glossary/webhook-signature) --- # Checkpoint A named point in a program that a job can restart from, so work already done is not done again. A checkpoint can save the browser session as it is at that moment. The next job that binds the session and sets resume_from_session skips straight past the login to the step after the checkpoint, and a job that has to switch to a heavier way of loading the page restarts from its last checkpoint instead of from the top. ``` { "checkpoint": { "name": "logged_in", "save_session": "acme" } } ``` ## Related - [Resumes where it stopped](https://kaab.ist/product/resume) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Automate logins with 2FA](https://kaab.ist/use-cases/login-with-2fa) - [Browser session](https://kaab.ist/glossary/browser-session) - [Side-effect fence](https://kaab.ist/glossary/side-effect-fence) --- # Drift The slow change of a website away from what a program was written against, until a step or a field stops matching. Kaabist watches for drift in canary runs and production jobs: candidates that stop matching, fields that come back empty, values outside their usual range. A program that drifted sends program.drift_detected. ``` { "type": "program.drift_detected", "data": { "program": "prg_4kTz", "field": "price", "kind": "fill_rate_drop", "source": "statistics" } } ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login) - [Canary run](https://kaab.ist/glossary/canary-run) - [Self-healing locator](https://kaab.ist/glossary/self-healing-locator) --- # Dry run Running a program without carrying out its side effects, to see that it reaches them and would do the right thing. A dry run goes through every step up to the first one that would change something on the site (a fenced step) and stops just before it, with the page and the data as they are at that moment. The test_program tool agents use runs this way by default, so building a form-filling program never files a real form. ``` kaab jobs run --program file-claim@production \n --input claim_id=0042 --dry-run --wait 60 ``` ## Related - [Never submits twice](https://kaab.ist/product/side-effects) - [Built by your coding agent](https://kaab.ist/product/mcp) - [Forms that must submit exactly once](https://kaab.ist/use-cases/submit-exactly-once) - [Side-effect fence](https://kaab.ist/glossary/side-effect-fence) - [Canary run](https://kaab.ist/glossary/canary-run) --- # Extract schema The description of the data a program returns: each field, where it is on the page, its type and the rules it must meet. A field can come from an element, a regular expression, JSON embedded in the page or a network response. Kaabist parses it into a real type (money, dates, numbers in any locale) and checks constraints, so you get typed data with warnings instead of strings that might be wrong. ``` { "title": "h1", "price": { "selector": ".price", "type": "money", "locale": "tr", "min": 0 }, "products": { "selector": ".product-card", "many": true, "min_items": 1, "fields": { "name": ".title", "url": { "selector": "a", "attr": "href", "type": "url" } } } } ``` ## Related - [API discovery](https://kaab.ist/product/api-discovery) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Pick sample](https://kaab.ist/glossary/pick-sample) - [API discovery](https://kaab.ist/glossary/api-discovery) --- # Headless browser A web browser that runs without a window, driven by a program instead of a person. Headless browsers load pages that need JavaScript. They are slower and costlier than plain HTTP requests, so Kaabist starts each job with the lightest way that works and only moves up to a browser when the page needs one. ``` { "options": { "prefer_tier": "http", "max_tier": "browser" } } ``` ## Related - [API discovery](https://kaab.ist/product/api-discovery) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Tier ladder](https://kaab.ist/glossary/tier-ladder) --- # Hosted resolve page A page Kaabist hosts where you, a teammate or your customer can answer what a paused job is waiting for, with no Kaabist account or integration. When a job awaits input with collect set to hosted, Kaabist emails a link to the address you choose: whoever has the answer, such as the owner of the phone that received the code. They type the value; the job resumes. ``` { "await_input": { "name": "otp", "collect": "hosted", "hosted": { "notify": "email", "to": "{{inputs.approver}}" } } } ``` ## Related - [Resumes where it stopped](https://kaab.ist/product/resume) - [Automate logins with 2FA](https://kaab.ist/use-cases/login-with-2fa) - [Await input](https://kaab.ist/glossary/await-input) - [Needs attention](https://kaab.ist/glossary/needs-attention) --- # Idempotency key A value sent with a request so that sending it again does not do the work again. Send the same Idempotency-Key with a job request and Kaabist returns the job it already created instead of starting another one. Together with side-effect fences, it means a network error on your side never turns into a second submission on the website. ``` curl https://api.kaab.ist/v1/jobs \ -H 'Authorization: Bearer $KAAB_API_KEY' \ -H 'Idempotency-Key: claim-2026-10-10-0042' \ -d '{"program": "file-claim@production", "inputs": {"claim_id": "0042"}}' ``` ## Related - [Never submits twice](https://kaab.ist/product/side-effects) - [Forms that must submit exactly once](https://kaab.ist/use-cases/submit-exactly-once) - [Side-effect fence](https://kaab.ist/glossary/side-effect-fence) --- # Landmark A named condition that says where a program is, such as being on the login page or being logged in. Landmarks let a job recognise pages instead of assuming them. logged_in and login_page are reserved: Kaabist uses them to check a session is still valid and to tell a redirect to the login page from a page that genuinely changed. ``` { "landmarks": { "login_page": { "visible": "form[action*=login]" }, "logged_in": { "url": "**/dashboard" } } } ``` ## Related - [Sessions and schedules](https://kaab.ist/product/sessions-and-schedules) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Browser session](https://kaab.ist/glossary/browser-session) - [Session probe](https://kaab.ist/glossary/session-probe) --- # Locator candidates An ordered list of ways to find the same element, tried in turn until one matches exactly one element. Candidates are ranked by how stable they tend to be: a test id first, then a role with an accessible name, a stable id, exact text, and positional CSS last. A candidate that matches several elements is skipped rather than guessed at. ``` { "fill": { "candidates": [ { "testid": "email" }, { "role": "textbox", "name": "Email" }, "#email" ] }, "value": "{{inputs.email}}" } ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Self-healing locator](https://kaab.ist/glossary/self-healing-locator) --- # MCP (Model Context Protocol) An open protocol that lets AI applications such as coding agents call tools provided by other services. Kaabist's MCP server gives an agent a real browser, a page view with ranked locators, extraction it can try on the live page, and the tools to turn what it did into a program, lint it and test it. Publishing and side effects need scopes you grant. ``` claude mcp add --transport http kaab https://mcp.kaab.ist/mcp ``` ## Related - [Built by your coding agent](https://kaab.ist/product/mcp) - [Browser automation for coding agents](https://kaab.ist/use-cases/coding-agents) - [Program](https://kaab.ist/glossary/program) - [Dry run](https://kaab.ist/glossary/dry-run) --- # Needs attention The state of a job that stopped because something got in the way that you need to decide on, kept so it can continue rather than fail. A page the program has never seen, a captcha the policy says to stop at, a session that expired with no way to refresh it: the job pauses with a snapshot of the page and a reason, sends you a webhook, and resumes from where it stopped once you resolve it. ``` { "type": "job.needs_attention", "data": { "job": "job_7Qp2", "reason": "unknown_page", "program": "acme-report@3", "url": "https://api.kaab.ist/v1/jobs/job_7Qp2" } } ``` ## Related - [Resumes where it stopped](https://kaab.ist/product/resume) - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login) - [Await input](https://kaab.ist/glossary/await-input) - [Webhook signature](https://kaab.ist/glossary/webhook-signature) --- # Network capture Reading the JSON a page receives from its own server while it loads, instead of reading what it draws. A capture_response step waits for a request that matches a URL pattern and stores its JSON, or the part a JSONPath selects. It is the most reliable way to read data that a page renders from an API. ``` { "capture_response": { "url": "**/api/orders*", "method": "GET", "json": "$.items", "into": "vars.orders" } } ``` ## Related - [API discovery](https://kaab.ist/product/api-discovery) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [API discovery](https://kaab.ist/glossary/api-discovery) - [Extract schema](https://kaab.ist/glossary/extract-schema) --- # Obstacle Anything that covers the page a program wants to use: a cookie banner, a newsletter dialog, a product tour, a chat bubble. Before every element action Kaabist looks for what is in the way and clears it: the site's known recipe first, then the dialog's own close button, a dismiss word in any of fourteen languages, Escape, a click on the backdrop, and only then hiding it. When nothing works, the job pauses and shows you a picture of the obstacle instead of clicking blind. ``` { "options": { "obstacles": { "allow_hide": false, "ignore": [ "#chat-widget" ] } } } ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Resumes where it stopped](https://kaab.ist/product/resume) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Needs attention](https://kaab.ist/glossary/needs-attention) - [Takeover](https://kaab.ist/glossary/takeover) --- # Pagination Reading a list that is split across pages, by following the next link until there is none or a limit is reached. A paginate step extracts the same schema from each page and joins the lists. It stops at max_pages, when a condition you set holds, or when the next button is gone, so a site that adds a thousand pages overnight cannot run up your bill. ``` { "paginate": { "next": { "role": "link", "name": "Next" }, "max_pages": 20 }, "extract": { "rows": { "selector": "tbody tr", "many": true, "fields": { "id": "td:first-child" } } } } ``` ## Related - [API discovery](https://kaab.ist/product/api-discovery) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Extract schema](https://kaab.ist/glossary/extract-schema) --- # Pick sample The value a field had when it was picked on the page, kept with the field as a permanent test. When you pick a price on the page, Kaabist stores what it read and what it parsed. Lint checks the field still parses the sample, replays check the snapshot still yields it, and a healing fix must return a value of the same type and size before it is proposed. ``` { "price": { "selector": ".price", "type": "money", "locale": "tr", "sample": { "raw": "1.299,90 TL", "value": 1299.9 } } } ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Extract schema](https://kaab.ist/glossary/extract-schema) - [Self-healing locator](https://kaab.ist/glossary/self-healing-locator) --- # Program A versioned JSON definition of a web automation: its inputs, steps, extraction and policies. Programs are recorded in the visual builder, produced by a coding agent over MCP, or written by hand as JSON; all three make the same document. Each published version is kept; jobs run a named version or an alias such as production, and proposed fixes become new versions you can diff. ``` { "kaab": "1", "name": "acme-report", "inputs": { "report_id": { "type": "string", "pattern": "^[0-9]+$" } }, "steps": [ { "goto": "https://portal.example.com/reports/{{inputs.report_id}}" }, { "extract": { "title": "h1", "total": { "selector": ".total", "type": "money" } } } ] } ``` ## Related - [Visual builder and recorder](https://kaab.ist/product/builder) - [Built by your coding agent](https://kaab.ist/product/mcp) - [Self-healing locators](https://kaab.ist/product/self-healing) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Recorder](https://kaab.ist/glossary/recorder) - [MCP (Model Context Protocol)](https://kaab.ist/glossary/mcp) - [Proposal](https://kaab.ist/glossary/proposal) --- # Program alias A name such as production that points at one version of a program and can be moved without changing the code that runs it. Jobs and schedules run acme-report@production; you test version 4, then move production to it. A bad release is rolled back by moving the alias back. ``` kaab programs alias set acme-report production 4 ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Sessions and schedules](https://kaab.ist/product/sessions-and-schedules) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Program](https://kaab.ist/glossary/program) - [Proposal](https://kaab.ist/glossary/proposal) --- # Proposal A suggested change to a program, such as a repaired locator, that waits for you to approve it before it becomes a new version. Healing never rewrites a published program silently. It opens a proposal with the diff and the evidence; you approve it, optionally promoting it to production, or reject it. ``` kaab proposals list --program acme-report kaab proposals approve prp_93Hd --promote ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Self-healing locator](https://kaab.ist/glossary/self-healing-locator) - [Drift](https://kaab.ist/glossary/drift) --- # Recorder The part of Kaabist's builder that turns what you do in a live browser into the steps of a program. You click through the site in a real Kaabist browser; each click, field and choice is saved as a step with ranked locator candidates to fall back on. Password values become secret inputs, a one-time code field becomes a wait for your answer, and the recorder proposes checks that the page looks right. What it records is ordinary program JSON, so you can edit it in the builder, push it with the CLI or hand it to your coding agent. ``` { "click": { "candidates": [ { "testid": "sign-in" }, { "role": "button", "name": "Sign in" }, { "css": "form#login button[type=submit]" } ] } } ``` ## Related - [Visual builder and recorder](https://kaab.ist/product/builder) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login) - [Program](https://kaab.ist/glossary/program) - [Locator candidates](https://kaab.ist/glossary/locator-candidates) - [Pick sample](https://kaab.ist/glossary/pick-sample) --- # Self-healing locator A way of finding an element on a page that survives when the page changes, by trying several candidates and repairing itself when all of them miss. Kaabist records every element with ranked candidates: a test id, a role and name, a stable id, exact text. When a site is redesigned and none of them matches, the job compares the page with its last good snapshot, finds the element that plays the same part, and proposes the new locator for you to approve. ``` { "click": { "candidates": [ { "testid": "export-button" }, { "role": "button", "name": "Export" }, { "text": "Export", "exact": true } ] } } ``` ## Related - [Self-healing locators](https://kaab.ist/product/self-healing) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Locator candidates](https://kaab.ist/glossary/locator-candidates) - [Proposal](https://kaab.ist/glossary/proposal) - [Drift](https://kaab.ist/glossary/drift) --- # Session probe A quick check, before a job starts, that a saved login is still valid. The probe loads a landmark page with the session. If the site sends it to the login page, the session is marked expired and the program signs in again, the job pauses for you, or it fails, as the program's policy says. The probe uses plain HTTP unless the page needs a browser. ``` { "options": { "session": "acme", "session_probe": "browser" }, "policies": { "on_session_expired": "park" } } ``` ## Related - [Sessions and schedules](https://kaab.ist/product/sessions-and-schedules) - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login) - [Browser session](https://kaab.ist/glossary/browser-session) - [Landmark](https://kaab.ist/glossary/landmark) --- # Side-effect fence A guard around a step that changes something in the world, such as submitting a form or paying, so it is never done twice. A step marked side_effect is recorded just before it runs and again once it has worked. If a job stops or retries after the fence was crossed, it does not press the button again; it checks what happened and reports it. Fenced steps cannot be retried automatically or made optional. ``` { "click": { "role": "button", "name": "Submit claim" }, "side_effect": true, "expect": { "visible": { "text": "Claim received" } } } ``` ## Related - [Never submits twice](https://kaab.ist/product/side-effects) - [Forms that must submit exactly once](https://kaab.ist/use-cases/submit-exactly-once) - [Idempotency key](https://kaab.ist/glossary/idempotency-key) - [Checkpoint](https://kaab.ist/glossary/checkpoint) - [Dry run](https://kaab.ist/glossary/dry-run) --- # Takeover You or a teammate stepping into a paused job's live browser to do the one thing the program could not, then handing it back. From the attention inbox in your Kaabist panel, one click opens the job's browser where it stopped. You close the dialog, pick the right row or solve the check; the job continues from there, and what you did can be remembered for the next time the site does the same. ``` kaab jobs takeover job_7Qp2 # opens the browser where the job stopped; do the step, then: kaab jobs resume job_7Qp2 --continue ``` ## Related - [Resumes where it stopped](https://kaab.ist/product/resume) - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login) - [Needs attention](https://kaab.ist/glossary/needs-attention) - [Obstacle](https://kaab.ist/glossary/obstacle) --- # Tier ladder The order in which Kaabist tries ways of loading a page: plain HTTP first, then a browser, then a stealth browser, stopping at the cap you set. A job starts on the lightest tier that can do its work. When the page needs more, the job moves up a tier and restarts from its last checkpoint at the next tier. max_tier caps how far it may go. ``` { "options": { "prefer_tier": "http", "max_tier": "stealth" } } ``` ## Related - [Resumes where it stopped](https://kaab.ist/product/resume) - [API discovery](https://kaab.ist/product/api-discovery) - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api) - [Headless browser](https://kaab.ist/glossary/headless-browser) - [Checkpoint](https://kaab.ist/glossary/checkpoint) --- # Webhook signature A header that proves a webhook came from the service that claims to have sent it and was not changed on the way. Every Kaabist delivery carries a Kaab-Signature header with a timestamp and an HMAC-SHA256 of the raw body. Verify it on the bytes as received, before parsing; each SDK does it in one call. ``` Kaab-Signature: t=1758362400,v1=5257a869e7ec… webhooks.verify(rawBody, signatureHeader, secret) ``` ## Related - [Sessions and schedules](https://kaab.ist/product/sessions-and-schedules) - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login) - [Needs attention](https://kaab.ist/glossary/needs-attention) - [Change detection](https://kaab.ist/glossary/change-detection) --- # Kaabits, Kaabist, kaab.ist: where the name comes from Kaabist · 10 October 2026 Kaabist comes from kaabits, Estonian for scraper. We bent it so the domain could be kaab.ist: .ist for Istanbul, where it is made, and -ist for someone who practises a craft. The logo is a spider's two eyes. Every product name is a small bet. Ours started with a word we could not pronounce at first. ## Kaabits *Kaabits* is Estonian for scraper: the tool you drag across a surface to take something off it. That is how this project began. We were getting data out of web pages that did not want to give it: pages behind logins, pages that change every few weeks, pages that ask for a code sent to someone's phone. A scraper is a fine thing to be. But the longer we worked, the less the job looked like scraping. The hard part was never reading the page. It was everything around it: logging in again when a session expired, waiting for the account owner to type a code, not pressing *Submit* twice after a crash, and noticing when the site had moved a button. ## Kaabist So we bent the word. *Kaabits* became *Kaabist*, and the name started to carry two more meanings. - **.ist is Istanbul.** The domain is `kaab.ist`, and `.ist` is the city's own top-level domain. Kaabist is made in Istanbul, and the address says so. - **-ist is the one who does it.** In English, *-ist* is the suffix for someone who practises a craft: a machinist, a typist, a cellist. A kaabist is someone whose craft is getting work done on the web, reliably. Inside the code, the short form stayed: the command is `kaab`, the API lives at `api.kaab.ist`, and programs start with `"kaab": "1"`. Everywhere a person reads it, it is Kaabist. ## The eyes The mark looks like two letters. It is a spider's two eyes. Spiders crawl the web, which is what our programs do. And when a thread breaks, a spider goes to the break and mends it. That is the part we cared about most: when a website changes and a step stops working, Kaabist finds what changed, proposes the fix, and waits for you to approve it. On this site the eyes blink, look around and walk to the broken thread. It is the same idea, drawn. ## What stays the same The name changed; the craft did not. We still get data out of pages. We just also log in, wait, remember where we stopped, refuse to do anything important twice, and mend what breaks. --- # Why a form should never submit twice Kaabist · 10 October 2026 Retrying is the right answer to most failures in web automation, and the wrong one for a submit. Kaabist fences every step that changes something: it records that it is about to act, acts, and records that it did. A job that finds an open fence never acts again; it stops and asks you. Most failures in web automation have the same cure: try again. A page loaded slowly, a request timed out, a worker restarted. Run the step once more and it usually works. There is one kind of step where that cure is the disease. ## The step you cannot take back Some steps change something in the world. They file an insurance claim, place an order, send a message, pay an invoice. Call them side effects. Now picture the moment it goes wrong. The program clicks **Submit**. The browser sends the request. Then the worker running the job disappears: the machine is replaced, the network drops, the process runs out of memory. Nobody saw the confirmation page. Did the claim go through? Nobody knows. The website might have received it, or not. And the automation's default instinct, *retry*, is the one answer that can turn one claim into two. Duplicates are expensive in exactly the places people automate most: insurance portals, government forms, supplier orders, payments. A duplicate claim is a phone call, a reversal, sometimes a penalty. Worse, it is often discovered weeks later. ## Fences Kaabist handles this with a fence. You mark the step: ```json { "click": { "role": "button", "name": "Submit claim" }, "side_effect": true, "expect": { "visible": { "text": "Claim received" } } } ``` Before the click, the engine writes down that it is **about to execute** this step. After the click, once the page shows what `expect` asks for, it writes down that the step was **executed**. Both records are saved outside the browser, so they survive whatever happens to it. If a job is resumed and finds a fence that says *about to execute* but never *executed*, it does not click again. It cannot know what happened, so it does not guess. It pauses with the reason `side_effect_ambiguous` (it cannot tell whether the step went through) and asks you, or the teammate you chose, to look at the portal and decide. Three more rules follow from the same idea: - A fenced step is never retried automatically, and it cannot be optional. - Restarting from a checkpoint can never go back past a side effect that already happened. - If a job is stopped while a fence is open, it waits for you to decide instead of being put back in the queue. ## Your side of the wire The fence protects the website from the job. Your code also needs protecting from the network between you and Kaabist: you send a request to start a job, the connection drops, and you do not know whether the job was created. That is what an idempotency key is for. Send the same `Idempotency-Key` with the same request and Kaabist returns the job it already created instead of starting another one: ``` curl https://api.kaab.ist/v1/jobs \ -H "Authorization: Bearer $KAAB_API_KEY" \ -H "Idempotency-Key: claim-0042" \ -d '{"program": "file-claim@production", "inputs": {"claim_id": "0042"}}' ``` Together, the two make the whole path once-only: your request creates one job, and that job presses the button at most once. ## Testing without filing A fence also gives you a clean way to test. A dry run goes through every step up to the first fenced one and stops just before it. You see that the program logs in, fills the form and reaches the button, and nothing is filed. Coding agents that build programs through Kaabist's MCP server test this way by default. ## Once, or you decide Retrying is how automation becomes reliable. Refusing to retry, in exactly the right place, is how it becomes trustworthy. A submit happens once, or you decide what happens next. --- # Changelog Every change to Kaabist that you would notice, newest first, with the day it shipped. ## Virus scan keeps up with large PDFs 2026-11-02 Downloads and PDFs up to 64 MB are scanned before they reach you. ## Model tokens priced per model 2026-10-28 Input and output tokens show up apart on your bill, each at its model's own price. ## 64 MB downloads and responses 2026-10-27 The cap for downloads, responses and PDFs went up to 64 MB. ## Sturdier PDF tables 2026-10-26 read_pdf keeps overprinted headers and single-cell rows inside a table, and drops a stray row of column numbers. ## One billing account for several organisations 2026-10-26 A single billing account can now pay for more than one organisation. ## Read tables from PDFs 2026-10-25 The read_pdf step turns a PDF's tables into rows your program can use, billed per band of pages. ## Stealth tier on two browser engines 2026-10-20 A stealth job starts on a hardened Chromium; a site that refuses it is retried on Firefox. ## Follow a link to where it lands 2026-10-20 An extracted link can ask where it redirects, so you get the final address instead of a tracking hop. --- # We started as a scraper. Then we kept going. Kaabist is an API that does work on websites for you, and keeps doing it: programs that log in, wait for your 2FA code, never submit twice, and mend themselves when a site changes. It is made in Istanbul. ## Kaabits, a scraper. Kaabist, the one who does it. Kaabits is Estonian for scraper. That is where we began: getting data out of pages that did not want to give it. We bent the word into Kaabist. The .ist is Istanbul, where Kaabist is made, and -ist is the English suffix for someone who practises a craft. The mark is a spider's two eyes. Spiders crawl the web, and when a thread breaks, they mend it. So do our programs. ## Automation is a promise that has to hold. - **Programs, not improvisation** A flow that matters should run the same way every time. Models help us build programs and heal them; they do not improvise each run. - **You stay in the loop** Some steps need you: a code, an approval, a judgment call. A job should wait for you, not fail, and not start over. - **Nothing important happens twice** A submit, a payment, an order: once, or not at all. A crash is never a reason to guess. - **Honest about others** We compare ourselves using other products' own documentation, with a source and a date for every claim, and we correct what we get wrong. ## Part of Claude Startups. Kaabist is a member of Claude Startups, Anthropic’s program for startups building with Claude. ## Bring us a flow that keeps breaking. --- # Your logins, sessions and data stay yours. Kaabist runs on infrastructure it operates itself, in the EU. Secrets are encrypted per organisation, job traffic leaves through a single guarded gateway, and every sensitive action is written to an audit log. ## Six things we never cut corners on. - **Encrypted per organisation** Stored passwords, sessions and provider credentials use envelope encryption: a data key per organisation, wrapped by a master key in OpenBao. Plain text never leaves the worker's memory. - **Redacted before capture** Password fields are redacted before a page is snapshotted or screenshotted. Secrets never appear in logs, snapshots, screenshots or webhooks. - **One way out** Job traffic reaches the internet only through Kaabist's egress gateway. It refuses private, loopback, link-local and metadata addresses, and connects only to the address it checked. - **Isolated browsers** Browser contexts run with site isolation and no file system access. Files leave only through an explicit download step, capped at 20 MB. - **Short-lived access** Live views and hosted pages use tokens scoped to one job that expire after 15 minutes. Screencast frames are never stored. - **Everything sensitive is audited** Approvals, takeovers, key and role changes, sessions, billing, exports and deletions are logged with who did it, from where, and when. ## In the EU by default. Deleted when you say. The platform runs on servers in Finland with backups in Germany, and the EU is the default region. Kaabist follows the GDPR, and KVKK for its entity in Türkiye. An organisation can delete its data through the API: snapshots, results and sessions are purged within 24 hours. The list of sub-processors and the data processing agreement are published with our legal pages. Found a vulnerability? Write to security@kaab.ist. ## Questions from your security team? We will answer them. --- # What Kaabist does Everything Kaabist does: build a program in the visual builder, with a coding agent or as JSON; run it on a schedule, a call or a batch; and keep it working when the site changes. - [Resumes where it stopped](https://kaab.ist/product/resume): Some steps only you can finish: a one-time code, a captcha, an approval. Kaabist pauses the run right there and emails a link to you, or to the teammate or customer you choose. Once they answer, the program continues from its last checkpoint. Nothing starts over. - [Visual builder and recorder](https://kaab.ist/product/builder): Record the task in a live Kaabist browser, pick the data you want, and edit the steps and the JSON side by side. Test any step against the real site before you publish. No agent and no code needed, and nothing hidden when you want them. - [Built by your coding agent](https://kaab.ist/product/mcp): Connect Claude Code, Codex or Cursor to mcp.kaab.ist. Your agent opens a real Kaabist browser, works through the site with you, and what it does becomes a program: versioned, linted, and tested with a dry run before it ever submits anything. - [Never submits twice](https://kaab.ist/product/side-effects): Mark the steps that change something (a submit, a payment, an order) as side effects. Kaabist writes each one down just before it runs and again once it has worked. If a server crashes in between, Kaabist never presses the button again on its own: it pauses and asks you to check. - [Self-healing locators](https://kaab.ist/product/self-healing): Every target is recorded with several ranked locators and a fingerprint of the element it found. When the site changes and they stop matching, Kaabist finds the element again, writes the fix down as a proposal, and lets you promote it to a new version. - [API discovery](https://kaab.ist/product/api-discovery): On a browser run, Kaabist watches the network for the JSON response that carries the values you extract. Once it has verified that endpoint, later runs read it directly on the HTTP tier: faster, and cheaper in credits. - [Sessions and schedules](https://kaab.ist/product/sessions-and-schedules): A session keeps a site's login between jobs, so later runs skip straight past it. A schedule runs a program on a cron, compares each result with the last, and sends an event only when the data actually changed. ## Build - **Visual builder** A step list and the JSON side by side, in sync, linted as you type. - **Recorder** Click through the site in a live Kaabist browser; each action becomes a step. - **Picker** Pick a value, select similar for a list, across frames and shadow DOM. - **Coding agents** Claude Code, Codex or Cursor over MCP, signed in with OAuth, in test mode first. - **Programs as files** Pull, diff, lint and push program JSON with the CLI, from your repository. - **Versions and aliases** Every publish is a version with a diff; an alias such as production picks one. ## Run - **API and SDKs** REST, TypeScript, Python and Go, with idempotency keys. - **Schedules** Cron with a time zone, overlap and catch-up rules, and change detection. - **Batches** Up to 1,000 inputs in one call, followed as one batch. - **Tiers learned per site** Plain HTTP where it works, a real browser where it must, picked per site. - **Estimates and dry runs** The cost before a run; a dry run stops before the first submit. - **Test keys** Real runs on their own small daily quota, kept for a day. ## Keep working - **Self-healing** A moved element is found again; the fix is a proposal you approve. - **Drift warnings** Canary runs and fill rates warn you before your own runs fail. - **Popups cleared** Cookie banners, modals and product tours closed before they block a click. - **Captcha policy** Per program: pause for a person, solve, or fail. - **API discovery** The JSON behind a page is found, and later runs skip the browser. ## People in the loop - **Resumes where it stopped** A 2FA code or a question pauses the run; it continues from its checkpoint. - **Hosted answer page** You, a teammate or your own customer answers from a link Kaabist sends. - **Take over live** Watch a run in its browser and step in; what you do becomes a proposed fix. - **Never submits twice** A step that submits runs once, even after a crash; then it asks you. ## Data - **Typed fields** Money, dates, numbers and links parsed by locale, checked, with warnings. - **Every kind of locator** CSS, XPath, text, role, test id, regex, embedded JSON, network responses. - **Downloads and screenshots** Files up to 64 MB named from your inputs; screenshots never, on failure or always. - **Sessions** Logins saved encrypted, checked before use, renewed by a program of their own. ## Deliver and operate - **Signed webhooks** About 25 events, retried for up to 12 hours, with Slack and Discord formats. - **Bring your own** Your proxies, LLM or captcha solver; that line leaves your bill. - **Teams** Roles from owner to viewer, two-factor sign-in for owners and admins, an audit log. - **Keys** Live and test keys with scopes, rotated with a grace period. - **Your data** Secrets kept out of logs, snapshots and screenshots; export or delete everything. --- # Use cases What teams automate with Kaabist. - [Scrape a website that requires login](https://kaab.ist/use-cases/scrape-behind-login): Portals, dashboards, supplier sites: the data you need sits behind a sign-in form. Kaabist runs the login as part of a program, keeps the session between jobs, and reads the pages as typed, validated fields. - [Automate logins with 2FA](https://kaab.ist/use-cases/login-with-2fa): One-time codes by e-mail or SMS, authenticator prompts, approval screens: a second factor is a step only the account owner can finish. Kaabist pauses the job there, emails a link to you (or the teammate or customer who owns the account), and resumes the program the moment the code is typed. - [Forms that must submit exactly once](https://kaab.ist/use-cases/submit-exactly-once): Some forms change the world when they are sent: an order is placed, money moves, an application is filed. Kaabist records those steps just before and just after they run (a fence), so a crash, a retry or a redeploy can never send them twice. - [Turn a website into an API](https://kaab.ist/use-cases/website-to-api): Describe the flow once as a program with inputs. From then on it is one HTTP call: inputs in, typed JSON out, with versions, aliases and webhooks, as if the site had shipped the API itself. - [Browser automation for coding agents](https://kaab.ist/use-cases/coding-agents): Coding agents are good at exploring a site and bad at doing it the same way twice. With Kaabist over MCP, the agent explores in a real browser, and what it learns becomes a fixed program that runs the same way every time, without the agent. - [Monitor pages behind a login](https://kaab.ist/use-cases/monitor-behind-login): Watch values that live behind a sign-in: a supplier's price list, a claim's status, an account's limits. Kaabist runs the program on a schedule, compares each result with the last, and calls your webhook only when something changed. --- # Compare Kaabist What each product does, and what only Kaabist does, from each product's own documentation. Every claim on a detailed page links to its source and carries the date it was verified. ## At a glance | Product | What it does | Waits for your 2FA code, then resumes | Never submits twice | Fixes itself, with your approval | Built by your coding agent | |---|---|---|---|---|---| | Kaabist | Runs your website tasks as programs that keep working | yes | yes | yes | yes | | [Airtop](https://kaab.ist/vs/airtop) | AI-built browser agents that run on schedules | partial | no | yes | no | | [Anchor Browser](https://kaab.ist/vs/anchor-browser) | Cloud browsers and AI-built browser tasks | partial | no | yes | yes | | [Apify](https://kaab.ist/vs/apify) | A marketplace of ready-made scrapers | no | no | no | yes | | [Browser Use](https://kaab.ist/vs/browser-use) | AI agents that do browser tasks from a prompt | partial | no | partial | yes | | [Browserbase](https://kaab.ist/vs/browserbase) | Remote browsers for your own code and agents | partial | no | partial | yes | | [Browserless](https://kaab.ist/vs/browserless) | Hosted browsers for your Playwright or Puppeteer code | partial | no | no | yes | | [Firecrawl](https://kaab.ist/vs/firecrawl) | Turns web pages into Markdown or JSON for LLMs | partial | no | unclear | yes | | [Playwright, by hand](https://kaab.ist/vs/playwright) | An open-source library to script a browser yourself | no | no | no | partial | | [Scrape.do](https://kaab.ist/vs/scrape-do) | A scraping API with rotating proxies | no | no | unclear | partial | | [Skyvern](https://kaab.ist/vs/skyvern) | AI agents that run browser workflows | partial | no | partial | yes | ## Detailed comparisons - [Kaabist vs Airtop](https://kaab.ist/vs/airtop): Airtop compiles described workflows into deterministic agents that run on schedules and heal through drafts you review and deploy. Kaabist shares the reviewable-healing approach and adds a pause mid-run that waits for your answer and continues from the last checkpoint, guards that record a submit before and after it runs so it never runs twice, an MCP server for coding agents, and API discovery. - [Kaabist vs Anchor Browser](https://kaab.ist/vs/anchor-browser): Anchor Browser is close to Kaabist in spirit: deterministic tasks that heal as reviewable drafts. Where they differ is what happens when a flow needs you and around a submit: any Kaabist program can pause at its last checkpoint until you answer, and every step that must not run twice is guarded. - [Kaabist vs Apify](https://kaab.ist/vs/apify): Apify is a platform and marketplace for running scrapers and automation tools called Actors, which you pick from its store or write yourself. Kaabist runs your own fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guard every step that submits so it runs once, heal through fixes you review, and discover a site's APIs to skip the browser. - [Kaabist vs Browser Use](https://kaab.ist/vs/browser-use): Browser Use runs AI agents that complete browser tasks from a prompt, plus remote browsers for your own agents. Kaabist runs fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guards every step that submits so it never runs twice, delivers healing as fixes you review, and discovers a site's APIs. - [Kaabist vs Browserbase](https://kaab.ist/vs/browserbase): Browserbase is browser infrastructure: remote browsers for your code, and Stagehand for AI actions inside it. Kaabist runs whole programs on its own browsers: it pauses them when a site needs you, resumes them from their last checkpoint once you answer, and guards every step that submits. - [Kaabist vs Browserless](https://kaab.ist/vs/browserless): Browserless runs browsers for your code and hands a session to you well: a live link with a done button. Kaabist takes the step further: the program itself pauses until you answer, resumes from its last checkpoint, heals its locators, and never repeats a submit. - [Kaabist vs Firecrawl](https://kaab.ist/vs/firecrawl): Firecrawl turns pages into clean markdown or JSON for models, fast and at scale. Kaabist is for the flows around the data: logging in, waiting for your 2FA code, submitting once, and keeping that program working when the site changes. - [Kaabist vs Playwright, by hand](https://kaab.ist/vs/playwright): Playwright is the engine under a great deal of browser automation, Kaabist's included. Writing it by hand gives you total control and every operational problem: logins that expire, selectors that break, a 2FA code someone has to type at the keyboard, a retry that submits twice. - [Kaabist vs Scrape.do](https://kaab.ist/vs/scrape-do): Scrape.do is a scraping API that fetches pages through rotating datacenter, residential or mobile proxies, optionally in a headless browser with a list of actions, and charges only for successful requests. Kaabist runs fixed programs that pause when a site needs you and continue from their last checkpoint once you answer, guard every step that submits so it runs once, heal through fixes you review, work with coding agents over MCP, and discover a site's APIs to skip the browser. - [Kaabist vs Skyvern](https://kaab.ist/vs/skyvern): Skyvern is an AI agent platform that runs browser workflows and caches successful runs as code that is regenerated by the agent when a page changes. Kaabist runs fixed programs that pause when a site needs you (a 2FA code, an approval) and continue from their last checkpoint once you answer, guards every step that submits so it never runs twice, delivers healing as fixes you review, and discovers a site's APIs. --- # Integrations Coding agents, SDKs, the CLI and webhooks. - [Claude Code](https://kaab.ist/integrations/claude-code): Add Kaabist to Claude Code with one command. Claude opens a real Kaabist browser, works through the site, and turns what it did into a program you review, test and publish. - [Codex](https://kaab.ist/integrations/codex): Point Codex at Kaabist's MCP server and it can drive a real browser on Kaabist's pool, read pages through ranked locators, and save what works as a draft program. - [Cursor](https://kaab.ist/integrations/cursor): Add Kaabist to Cursor's MCP servers. The agent in your editor opens Kaabist browsers, tries extracts on the live page, and writes the program next to your code. - [TypeScript SDK](https://kaab.ist/integrations/typescript): @kaabist/sdk gives you every API operation as a typed method, retries that never run a job twice, and a wait helper that can answer a job's questions as it goes. - [Python SDK](https://kaab.ist/integrations/python): The kaabist package covers the whole API for Python 3.11 and later, with typed models, pages that fetch as you iterate, and a wait that can answer a job's questions as it goes. - [Go SDK](https://kaab.ist/integrations/go): github.com/kaabist/kaab-go gives Go services the full API with typed errors, retries with idempotency keys, and iterators over every list. - [kaab CLI](https://kaab.ist/integrations/cli): The kaab command runs jobs, pushes and pulls programs, approves proposals and creates schedules. It fits in scripts and pipelines: exit codes say what happened. - [Webhooks](https://kaab.ist/integrations/webhooks): Kaabist sends signed events to your endpoints: jobs that finish, wait for input or need attention, schedules that found a change, programs that drifted. Deliveries are retried with backoff and can go straight to Slack or Discord. --- # Kaabist pricing Every plan pays in credits for what runs: HTTP requests, browser time, proxies and captchas, priced the same on every plan. ## Plans | Plan | Credits a month | Seats | Highest tier | Browsers at once | Results kept | |---|---|---|---|---|---| | Free | 500 | 1 | http | 0 | 7 days | | Developer | 10000 | 3 | stealth | 4 | 30 days | | Team | 60000 | 10 | stealth | 16 | 30 days | | Scale | 300000 | 30 | stealth | 64 | 90 days | | Enterprise | 1000000 | 100 | stealth | 200 | 90 days | ## What a run costs - HTTP request: 1 credit - Browser run: 5 credits, +1 per 10 s after 30 s - Stealth run: 20 credits, +1 per 10 s after 30 s - Proxy traffic: datacenter 0.05/MB · residential 0.5/MB · mobile 2/MB - Captcha solve: 2 credits - Model tokens: by model, e.g. claude-sonnet-5-5: 0.87 per 1k in, 4.4 per 1k out - Canary runs: 50% of a normal run --- # Referral programme Share your Kaabist link. When an organisation you refer makes its first payment, it gets 10% extra credits and you get 20% of the credits that payment bought. ## How it works 1. **Copy your link.** Every organisation has a referral link under Settings → Referrals in the panel. Share it wherever you like. 2. **They sign up through it.** The link is remembered for 30 days after the first click, so they can look around first. The first link they clicked counts. 3. **Their first payment.** When their organisation makes its first payment, they get 10% extra credits and you get 20% of the credits that payment bought. ## An example A new organisation's first payment is the Developer plan at $49 a month, which buys 10,000 credits. It gets 1,000 extra credits; you get 2,000 credits. ## Terms - Only the first payment of the organisation you referred earns a reward; later payments do not. - If that payment is refunded, the reward is reversed: credits not yet spent are removed. - Reward credits are valid for 12 months, then expire. - A sign-up counts once, for the first link used. Your own link does not count for your own organisation. - Rewards are credits on your Kaabist balance; they are not paid out as money. - We may hold a reward for review when a referral looks unusual, and change the rates for new referrals; a reward already given keeps its rate. --- # Glossary of web automation What the terms mean, how they work, and the code that uses them. - [API discovery](https://kaab.ist/glossary/api-discovery): Finding the JSON requests a website makes behind its pages, so data can be read from them instead of from the screen. - [Await input](https://kaab.ist/glossary/await-input): A step that pauses a job until you, a teammate or your own system supplies a value the program cannot know in advance, such as a one-time code. - [Browser session](https://kaab.ist/glossary/browser-session): A saved, named login state (cookies and storage) that jobs reuse so they do not log in every time. - [Canary run](https://kaab.ist/glossary/canary-run): A scheduled test run of a program that checks it still works on the live site before your real jobs find out it does not. - [Captcha policy](https://kaab.ist/glossary/captcha-policy): What a program does when a site asks it to prove it is human: pause and wait for you, solve it, or fail. - [Change detection](https://kaab.ist/glossary/change-detection): Running a program on a schedule and being told only when the fields you care about change. - [Checkpoint](https://kaab.ist/glossary/checkpoint): A named point in a program that a job can restart from, so work already done is not done again. - [Drift](https://kaab.ist/glossary/drift): The slow change of a website away from what a program was written against, until a step or a field stops matching. - [Dry run](https://kaab.ist/glossary/dry-run): Running a program without carrying out its side effects, to see that it reaches them and would do the right thing. - [Extract schema](https://kaab.ist/glossary/extract-schema): The description of the data a program returns: each field, where it is on the page, its type and the rules it must meet. - [Headless browser](https://kaab.ist/glossary/headless-browser): A web browser that runs without a window, driven by a program instead of a person. - [Hosted resolve page](https://kaab.ist/glossary/hosted-resolve-page): A page Kaabist hosts where you, a teammate or your customer can answer what a paused job is waiting for, with no Kaabist account or integration. - [Idempotency key](https://kaab.ist/glossary/idempotency-key): A value sent with a request so that sending it again does not do the work again. - [Landmark](https://kaab.ist/glossary/landmark): A named condition that says where a program is, such as being on the login page or being logged in. - [Locator candidates](https://kaab.ist/glossary/locator-candidates): An ordered list of ways to find the same element, tried in turn until one matches exactly one element. - [MCP (Model Context Protocol)](https://kaab.ist/glossary/mcp): An open protocol that lets AI applications such as coding agents call tools provided by other services. - [Needs attention](https://kaab.ist/glossary/needs-attention): The state of a job that stopped because something got in the way that you need to decide on, kept so it can continue rather than fail. - [Network capture](https://kaab.ist/glossary/network-capture): Reading the JSON a page receives from its own server while it loads, instead of reading what it draws. - [Obstacle](https://kaab.ist/glossary/obstacle): Anything that covers the page a program wants to use: a cookie banner, a newsletter dialog, a product tour, a chat bubble. - [Pagination](https://kaab.ist/glossary/pagination): Reading a list that is split across pages, by following the next link until there is none or a limit is reached. - [Pick sample](https://kaab.ist/glossary/pick-sample): The value a field had when it was picked on the page, kept with the field as a permanent test. - [Program](https://kaab.ist/glossary/program): A versioned JSON definition of a web automation: its inputs, steps, extraction and policies. - [Program alias](https://kaab.ist/glossary/program-alias): A name such as production that points at one version of a program and can be moved without changing the code that runs it. - [Proposal](https://kaab.ist/glossary/proposal): A suggested change to a program, such as a repaired locator, that waits for you to approve it before it becomes a new version. - [Recorder](https://kaab.ist/glossary/recorder): The part of Kaabist's builder that turns what you do in a live browser into the steps of a program. - [Self-healing locator](https://kaab.ist/glossary/self-healing-locator): A way of finding an element on a page that survives when the page changes, by trying several candidates and repairing itself when all of them miss. - [Session probe](https://kaab.ist/glossary/session-probe): A quick check, before a job starts, that a saved login is still valid. - [Side-effect fence](https://kaab.ist/glossary/side-effect-fence): A guard around a step that changes something in the world, such as submitting a form or paying, so it is never done twice. - [Takeover](https://kaab.ist/glossary/takeover): You or a teammate stepping into a paused job's live browser to do the one thing the program could not, then handing it back. - [Tier ladder](https://kaab.ist/glossary/tier-ladder): The order in which Kaabist tries ways of loading a page: plain HTTP first, then a browser, then a stealth browser, stopping at the cap you set. - [Webhook signature](https://kaab.ist/glossary/webhook-signature): A header that proves a webhook came from the service that claims to have sent it and was not changed on the way. --- # Blog Notes from Kaabist on web automation that keeps working. - [Kaabits, Kaabist, kaab.ist: where the name comes from](https://kaab.ist/blog/the-name): Kaabist comes from kaabits, Estonian for scraper. We bent it so the domain could be kaab.ist: .ist for Istanbul, where it is made, and -ist for someone who practises a craft. The logo is a spider's two eyes. - [Why a form should never submit twice](https://kaab.ist/blog/never-submit-twice): Retrying is the right answer to most failures in web automation, and the wrong one for a submit. Kaabist fences every step that changes something: it records that it is about to act, acts, and records that it did. A job that finds an open fence never acts again; it stops and asks you. --- # Legal Our legal documents live in the same repository as the code. - [Terms of Service](https://kaab.ist/legal/terms-of-service) - [Privacy Policy](https://kaab.ist/legal/privacy-policy) - [Acceptable Use Policy](https://kaab.ist/legal/acceptable-use-policy) - [Data Processing Agreement](https://kaab.ist/legal/dpa) - [Sub-processors](https://kaab.ist/legal/subprocessors) - [Cookie Policy](https://kaab.ist/legal/cookie-policy) --- # Kaabist brand Kaabist comes from kaabits, Estonian for scraper, bent to fit kaab.ist: .ist for Istanbul, where it is made, and -ist for the one who does the job. The mark is a spider's two eyes. - [Where the name comes from](https://kaab.ist/blog/the-name)