August 14, 2026Ceren Kaya Akgün
AI Web Scraping: Read the Page Once, Not Every Run
AI web scraping tools promise no selectors and no maintenance. The benchmarks say the opposite design wins. What the numbers actually show. →
TL;DR: Every AI web scraping product sells the same promise: no selectors, no maintenance, just describe the data. The promise is real for one page. It quietly inverts at scale, because a scraper with no selectors has to read every page on every run. The one public benchmark that measures extraction rather than navigation found that state of the art web agents recovered 31% of the data, while a system that used the model once to write a reusable extractor and then replayed it recovered 66% at roughly a third of the cost per row. This post covers what the numbers actually say, the failure mode nobody sells against, and how to build the replay design as a workflow.
Key Takeaways:
- Reading the page on every run is a design choice with a measured price, not a free upgrade. WebLists put state of the art web agents at 31% recall against 66% for a saved, replayed extractor
- The cost model flips at volume. Per run model reading scales with pages times runs; a saved extractor charges you once and then costs browser time
- Breaking is the good failure. A saved extractor that matches the wrong element returns a confident wrong value and nothing looks broken, which is why validation beats a better model
- How you hand the page to the model matters more than which model you pick. Flat JSON input scored F1 0.9567 against slimmed HTML and hierarchical JSON in the NEXT-EVAL benchmark
- Ambitious schemas collapse. ExtractBench recorded 0% valid output on a 369 field schema across every frontier model tested, so ask for the fields you will use and no more
Table of Contents
- The Claim the Whole Category Makes
- What Is AI Web Scraping? Three Designs, One Name
- How Accurate Is AI Web Scraping?
- Why Rereading Every Page Is the Expensive Design
- Grok Bot and a Quiet Convergence
- What Happens When the Website Changes
- How You Hand Over the Page
- Ask for Fewer Fields
- Extraction That Can Fail Loudly
- Looking Less Like a Robot, Honestly
- Pages Behind a Login
- Building It in Heym
- How Much Does AI Web Scraping Cost?
- Legality and Etiquette
- FAQ
- References
The Claim the Whole Category Makes
Open any page on the first page of results for AI web scraping and you will find a version of the same sentence. Selectors are brittle. Websites change. Let the model read the page instead, and maintenance goes away.
IBM's explainer has a section heading for it, Reduced maintenance, and the supporting sentence is that AI powered scrapers "generalize and adapt across different designs and layouts." Firecrawl's guide frames the whole category as replacing brittle CSS selectors with semantic understanding. Both are well written. Neither contains a single number.
That absence is the interesting part. This is a category built on a claim about reliability and cost, sold almost entirely without measurement. Meanwhile the research that does measure it points the other way, and as far as I can tell, no page currently ranking for the term cites any of it.
What Is AI Web Scraping? Three Designs, One Name
Definition: AI web scraping is the use of a language model to turn web pages into structured data. It covers three distinct designs: an agent that reads every page at run time, a model that writes a reusable extractor once and then steps aside, and a fixed script that calls a model only for regions with no stable structure.
Before the numbers, the label needs splitting, because AI web scraping describes at least three arrangements that behave nothing alike.
| Design | What the model does | When it runs | Fails by |
|---|---|---|---|
| Agentic reading | Looks at each page and decides what to extract | Every page, every run | Missing rows quietly, cost growing with volume |
| Program synthesis | Writes a reusable extractor once, then steps aside | Once at authoring time, again on repair | The saved extractor drifting out of date |
| Hybrid steps | Handles only the parts with no stable structure | Once per fragile step, cached after | The unstructured region changing shape |
The marketing copy rarely tells you which one you bought. A hosted endpoint that takes a URL and a prompt and returns JSON is almost always the first design, because that is the only way it can work without knowing your target in advance. An ai powered web scraping tool that asks you to point and click at a field is usually building something closer to the second.
The naming is a reliable tell. When a product describes itself as an ai web scraping agent, it is nearly always the first row of that table, because agency is the thing being sold. That is fine for exploration and it is the wrong shape for a job that repeats.
They are worth telling apart because they land in different places on both axes anyone actually cares about: how much of the data you get, and what each row costs.
How Accurate Is AI Web Scraping?
Most web agent research measures navigation. Can the agent book the flight, fill the form, find the setting. That is a different task from pulling 400 rows off a paginated listing, and the researchers behind WebLists say so directly in their opening line: most recent work has focused on navigation and transaction tasks, "with little emphasis on extracting structured data at scale."
So they built a benchmark for the neglected half. WebLists is 200 data extraction tasks across four common business and enterprise use cases. Each task means navigating to a page, configuring it, and extracting a complete dataset against a defined schema. Complete is the operative word: the metric is recall, so leaving rows behind counts against you in a way that a question answering benchmark never captures.
| System | Recall on WebLists |
|---|---|
| Language models with search capability | 3% |
| State of the art web agents | 31% |
| BardeenAgent (writes a program, then replays it) | 66% |
Read the middle row again. The agentic design, the one the category is built on, recovered under a third of the data on realistic extraction jobs.
The top row deserves a note too. A model with web search asked to gather a dataset returned 3% of it. If your workflow is a chat assistant with browsing pointed at a listing page, that is roughly what you should expect, and it explains an experience many people have had without quite naming it.
What made the difference was not a bigger model. BardeenAgent converts its execution into a repeatable program: it "constructs a generalizable CSS selector to capture all relevant items on the page, then fits the operations to extract the data." The paper notes it is the first LLM agent to take advantage of the regular structure of HTML.
Key principle: The winning system did the thing the entire category says is obsolete. It built a CSS selector. The difference is that a model built it, once, instead of a human building it and maintaining it forever.
That is worth sitting with. The SERP's central argument is that selectors are the problem. The one benchmark that measures extraction at scale found that generating a selector and replaying it roughly doubled recall against agents that read the page fresh every time.
Why Rereading Every Page Is the Expensive Design
The same paper reports the other half: replaying a generated program cut cost per output row by about three times.
The arithmetic behind that is not subtle. If a model reads every page, your bill is a function of pages times runs.
| Job shape | Per run reading | Saved extractor |
|---|---|---|
| 5,000 products, daily | 5,000 model calls per day, forever | One authoring pass, then browser time |
| 200 listings, hourly | 4,800 model calls per day | Occasional repair calls only |
| 40 pages, weekly | 40 calls per week | Rounding error either way |
The bottom row is the honest caveat. At small volume, none of this matters, and per run reading is genuinely the faster thing to build. The design question only becomes a cost question when the job repeats.
There is a second cost that shows up later. A page sent to a model is tokens, and modern pages are large. Reading a heavy listing page on every run pushes context cost in a direction that AI agent cost optimization treats as a first order concern, and it is the kind of spend that grows quietly enough to need LLM cost alerts rather than a monthly review.
Grok Bot and a Quiet Convergence
On 11 August 2026, xAI opened the beta of Grok Bot, described in its own announcement as "your team of always-on agents" that "have their own computer, work inside tools and apps like you do." The part relevant here is how they reach systems that have no integration: the bots "sign into the tools you already use and work across apps, tools, and websites, including platforms with no clean API or MCP." It is in beta for SuperGrok Heavy, Cursor Ultra and Cursor Teams Premium subscribers, with an enterprise waitlist.
Now read how the announcement says you teach one:
"The best way for a Bot to learn your workflow is to ask it to follow along the next time you do a job. It watches the steps and remembers how you like the work done."
It "saves your workflow as a routine."
That is the WebLists finding, shipped as a product, by a company with no obvious reason to have read the paper. The most heavily resourced new entrant in agentic automation did not build a bot that reasons about the page from scratch every morning. It built one that watches once, saves a routine, and replays it.
I do not read that as a coincidence. Demonstrate once and replay is where this keeps landing, because it is the only arrangement where accuracy and cost move in the same direction instead of trading off. A web scraping ai agent that re-derives its plan every run is paying full price for a decision it already made correctly yesterday.
Two honest caveats about the comparison. Grok Bot is a general assistant, not a scraping tool, and it is days old with no published extraction benchmark. And the announcement lists no limitations or safety notes at all, which for a product whose whole premise is signing into your accounts is a gap worth noticing rather than a detail. The design convergence is the point, not the product.
What Happens When the Website Changes
Here is where I think the entire category, including the parts I agree with, stops too early.
Saving the extractor solves cost and it solves recall. It does not solve knowing whether today's numbers are real.
Consider what actually happens when a page changes under a saved selector. There are two outcomes and they could not be more different.
Every product page answers the first case. Browse.ai owns the People Also Ask slot for "What happens when websites change?" with an answer about resilience. Selector healing, which we shipped in Heym and which I still think is worth having, also only answers the first case.
The second case has no vendor answer because there is no product feature that fixes it. A price of 458.00 read off the wrong element is indistinguishable from a price of 458.00 read off the right one. It flows into your sheet, your dashboard, your pricing decision, and the first sign of trouble is a human noticing that a competitor's prices have looked oddly stable for three weeks.
Notable fact: A traditional scraper that breaks returns nothing, which is a signal. An extractor that drifts returns something, which is not. Silence is easier to notice than plausibility.
The ExtractBench authors put the underlying problem crisply when describing what a serious evaluation has to do: "omission must be distinguished from hallucination." That distinction is missing from almost every production scraping setup I have looked at, including some of ours before we added checks.
How You Hand Over the Page
One finding from the literature is unusually actionable and I have not seen it on a single ranking page.
NEXT-EVAL benchmarked deterministic heuristic algorithms against off the shelf language models for web data record extraction, and tested three ways of preprocessing the page first: slimming the HTML, hierarchical JSON, and flat JSON. Flat JSON input let the models reach an F1 of 0.9567 with minimal hallucination, ahead of both alternatives.
The practical reading: if you are handing raw HTML to a model and getting mediocre results, the fix may not be a better model at all. It may be that you are giving it the page in the worst of the available shapes. Reducing the page to a flat representation of the records before extraction is cheap, and it moves accuracy more than a model upgrade usually does.
This is also why the humble getVisibleTextOnPage step is more useful than it looks. Reading document.body.innerText and handing the model text rather than markup removes an entire class of confusion, along with a large amount of token weight.
Ask for Fewer Fields
The second actionable finding is a warning about ambition.
ExtractBench, published in February 2026, pairs documents with JSON schemas and human annotated gold labels, yielding 12,867 evaluatable fields across schemas ranging from tens to hundreds of fields. Its conclusion about frontier models is blunt: they "remain unreliable on realistic schemas," and performance "degrades sharply with schema breadth," ending in 0% valid output on a 369 field financial reporting schema across all tested models.
One caveat I want to state plainly rather than bury: ExtractBench measures PDF to JSON, not HTML to JSON. It is a document benchmark, and I am borrowing its finding about schema breadth rather than its absolute numbers. The mechanism it identifies, that asking for more fields at once degrades every field, is not specific to PDFs, and it matches what happens when you point an extractor at a page and ask for forty attributes per product. But it is an inference across substrates, and you should weigh it as one. The document side of this is covered separately in AI document processing.
The design rule that follows is easy: extract the fields you will actually use. If you need name, price, and availability, ask for name, price, and availability. A schema listing every attribute you might one day want is not future proofing, it is a measurable accuracy cost paid on every run.
Extraction That Can Fail Loudly
Putting the last three sections together gives a shape for a scrape that can be trusted. Four properties, in order of how much they buy you.
Make the fields nullable and say so
Instruct the model to return null rather than guess. A null is a visible gap. A guess is not.
Check something you know must be true
A listing page that has returned somewhere near 340 rows every morning for a month is making you a promise. The morning it returns 4, something changed, and the row count knew before you did. The same goes for a price outside a plausible band, or a required field that came back empty. A Condition node testing a row count floor catches more real problems than any amount of prompt engineering.
Route the failure to a person
A check that logs is a check nobody reads. Send the failing branch somewhere audible, and if the decision downstream is expensive or hard to reverse, put a human in the loop gate on it rather than a notification.
Keep the run inspectable
When a number looks wrong three weeks later, you want the run that produced it, the page state at the time, and the steps that executed. This is the ordinary case for AI agent observability, and scraped data has a longer half life than most workflow output, so the traces matter for longer.
One more thing that is easy to forget: the page you scraped is untrusted input. If its text later reaches a model that can take actions, you have handed a third party a writing surface into your prompt. That is the prompt injection problem arriving through the data rather than the instructions, and the mitigations in LLM guardrails apply to extracted content exactly as they apply to user input.
Looking Less Like a Robot, Honestly
A real obstacle that most editorial coverage skips: a stock Playwright browser announces itself. navigator.webdriver is true, the user agent says HeadlessChrome, Chromium runs with --enable-automation, and several browser surfaces that a normal Chrome fills in are empty. Plenty of sites treat that combination as a bot and serve you a challenge page, including sites you are entirely authorized to automate, such as your own admin panel or a vendor portal your company pays for.
We shipped a setting for this in Heym on 13 August 2026, labelled Reduce automation flags in the properties panel (playwrightStealth). It is off by default and applies to Steps mode only. What it does, precisely:
- Drops Chromium's
--enable-automationflag and sets--disable-blink-features=AutomationControlled - Sends a standard Chrome user agent with no
HeadlessChromein it - Restores browser surfaces Playwright leaves empty, including
window.chrome, plugins and mime types - Reports a typical GPU renderer string on Linux and Docker, where there is no GPU, rather than the software renderer default
And what it does not do, in the words of our own documentation, because this is the part that matters more than the feature list: it "does not hide that the session is driven over Chrome DevTools Protocol, and it is not a way to bypass site security, CAPTCHAs, or access controls."
That boundary is deliberate. A site that genuinely does not want automated access can still tell, and should still be able to tell. The setting exists so that a workflow you are permitted to run is not blocked by an incidental signal, not so that a workflow you are not permitted to run becomes possible.
Pages Behind a Login
"Can your scraper handle sites with login requirements?" is a live People Also Ask question, currently answered by a vendor about its own product. The general answer does not depend on the vendor.
Do not type a password on every run. Log in once, save the browser storage state, and restore it before the steps execute. Then verify the restore actually worked by checking that a selector only a signed in user can see is visible, and keep a short fallback login that runs only when that check fails.
In Heym that is four fields on the Playwright node: playwrightAuthEnabled to turn it on, playwrightAuthStateExpression pointing at a stored value such as $global.authState, playwrightAuthCheckSelector for the signed in check, and playwrightAuthFallbackSteps for the recovery path. The first main step has to be navigate, since the check runs against a loaded page.
The reason to prefer this over re-authenticating each time is not only speed. Every login is an event on the account, and a job that logs in 24 times a day looks different in a security log than one that logs in when its session expires.
Building It in Heym
What is Heym? Heym is an open source, self-hostable AI workflow automation platform (MIT with Commons Clause) built around a visual canvas, where triggers, language models, browser automation, RAG and human approval steps are nodes in one workflow. It is not related to the Yiddish word of the same spelling.
Heym is a self-hosted browser automation platform built around a workflow canvas, so a scrape is a node in a pipeline rather than a standalone script. The Playwright node does the browser work, and its documentation opens by naming web scraping as the first use case.
The step types that matter for extraction are navigate, scrollDown, getText, getAttribute, getHTML, getVisibleTextOnPage, and screenshot. The one that changes the economics is aiStep, which sends the page to a model with plain language instructions and gets back the same kinds of actions you could have written by hand.
Two options on that step are the whole argument of this post, expressed as checkboxes:
saveStepsForFuturewrites the generated actions back into the workflow. The first run pays for a model call. Every run after it replays fixed actions and pays nothing. This is the program synthesis design, as a toggle.autoHealModeasks the model for an alternative locator after a selector based step has failed twice, preferring role based and text based locators over CSS, which is what the Playwright locator documentation recommends for the same reason. Healing coversclick,type,fill,hoverandselectOptiononly, which are the actions where swapping the locator is a safe substitution.
Here is a working extractor built on that shape. It collects a listing on a schedule, extracts a narrow schema, and refuses to stay quiet when the result looks wrong.
View template JSON
{
"heym": true,
"nodes": [
{
"id": "scrape_setup_note",
"type": "sticky",
"position": {
"x": 380,
"y": 560
},
"data": {
"label": "SetupNote",
"note": "### Before you run\n- Replace the navigate URL with a page you are allowed to automate.\n- Open ReadListing and select your own LLM credential on the AI step.\n- Turn on Reduce automation flags only if the site blocks a stock Playwright browser.\n- RowCountSane is the point of this template. Set the floor from a real run, not from a guess.\n- Auto heal repairs click, type, fill, hover and selectOption steps only."
}
},
{
"id": "scrape_cron",
"type": "cron",
"position": {
"x": 60,
"y": 260
},
"data": {
"label": "EveryMorning",
"cronExpression": "0 7 * * *"
}
},
{
"id": "scrape_browser",
"type": "playwright",
"position": {
"x": 380,
"y": 260
},
"data": {
"label": "ReadListing",
"playwrightMode": "steps",
"playwrightHeadless": true,
"playwrightStealth": false,
"playwrightTimeout": 45000,
"playwrightSteps": [
{
"action": "navigate",
"url": "https://example.com/catalog"
},
{
"action": "aiStep",
"instructions": "Dismiss any cookie or region banner, then scroll until the full product list is loaded.",
"credentialId": "",
"model": "gpt-5.5",
"saveStepsForFuture": true,
"autoHealMode": true,
"sendScreenshot": false,
"aiStepTimeout": 30000
},
{
"action": "getVisibleTextOnPage",
"outputKey": "listingText",
"timeout": 3000
}
]
}
},
{
"id": "scrape_extract",
"type": "llm",
"position": {
"x": 720,
"y": 260
},
"data": {
"label": "ExtractRows",
"model": "gpt-5.5",
"systemInstruction": "Extract product rows from the supplied page text. Return JSON with a rows array. Each row has name, priceUsd and inStock. Every field is nullable. Return null for anything you cannot read directly from the text. Never infer, estimate or complete a value.",
"userMessage": "$ReadListing.results.listingText",
"jsonOutputEnabled": true
}
},
{
"id": "scrape_gate",
"type": "condition",
"position": {
"x": 1060,
"y": 260
},
"data": {
"label": "RowCountSane",
"condition": "$ExtractRows.json.rows.length >= 20"
}
},
{
"id": "scrape_store",
"type": "output",
"position": {
"x": 1400,
"y": 140
},
"data": {
"label": "StoreRows",
"outputSchema": [
{
"key": "rows",
"value": "$ExtractRows.json.rows"
},
{
"key": "rowCount",
"value": "$ExtractRows.json.rows.length"
}
]
}
},
{
"id": "scrape_alert",
"type": "slack",
"position": {
"x": 1400,
"y": 400
},
"data": {
"label": "TellSomeone",
"channel": "#data-watch",
"message": "Catalog scrape returned too few rows. The page probably changed. Count: $ExtractRows.json.rows.length"
}
}
],
"edges": [
{
"id": "scrape_e1",
"source": "scrape_cron",
"target": "scrape_browser"
},
{
"id": "scrape_e2",
"source": "scrape_browser",
"target": "scrape_extract"
},
{
"id": "scrape_e3",
"source": "scrape_extract",
"target": "scrape_gate"
},
{
"id": "scrape_e4",
"source": "scrape_gate",
"target": "scrape_store",
"sourceHandle": "true"
},
{
"id": "scrape_e5",
"source": "scrape_gate",
"target": "scrape_alert",
"sourceHandle": "false"
}
]
}The RowCountSane node is the part I would argue for hardest. It is four words of configuration and it converts the quiet failure into a loud one. A catalog that returns 340 rows on a normal day and 4 today has not returned a small dataset, it has returned a broken one, and without that gate the 4 rows would have been written to storage looking perfectly valid.
If you would rather start from something already published, the Playwright Visual AI Monitor template takes the screenshot route: it captures the page on a schedule and has a vision model look for layout breakage, which catches problems that text extraction cannot see. Both sit in the same family as the other AI workflow automation examples we have catalogued.
For onward routing, extracted rows are ordinary workflow data. They can go to a sheet, a database, or straight into a RAG pipeline if the point of the collection was to answer questions over it later.
Three things you only notice once it runs nightly
Cancelling one run should not kill the others. I spent this week on execution persistence and cancellation in Heym, and the case that prompted it is exactly this workload: long browser runs that a person starts, watches for a while, then navigates away from. Terminal results are now persisted even when the client disconnects, and stopping one execution stops that stream only, so sibling runs keep going. A scrape that quietly lost its result because someone closed a tab is a genuinely annoying bug to diagnose.
Auto heal reads the page. The heal path sends page HTML to a model, which means the untrusted content warning applies to the repair mechanism too, not just to the extracted data. That is one of the reasons healing is deliberately constrained to returning a single locator for a small set of actions rather than being allowed to propose arbitrary new steps.
Fixed steps cost nothing and cannot be redirected. Everything in the step list that is not an aiStep runs without a model call and without any opportunity for the page to influence what happens next. That property is the security argument in AI browser automation, and it applies here for free.
How Much Does AI Web Scraping Cost?
Worth being concrete, because the category is vague about it.
| Cost | Per run reading | Saved extractor |
|---|---|---|
| Model calls for navigation | Every page, every run | First run, then on repair only |
| Model calls for extraction | Every run | Every run (this one does not go away) |
| Browser time | Same | Same |
| Cost trend as runs grow | Linear | Nearly flat |
| Cost trend as pages grow | Linear | Linear, but on a much smaller coefficient |
Note the row that does not improve. Saving the navigation steps removes the navigation model calls, not the extraction ones: something still has to turn page text into structured rows on every run. You reduce that by extracting a narrow schema and by sending text rather than raw HTML, which are the two findings from the benchmarks above. You do not eliminate it, and any tool claiming otherwise is describing a regex.
If you want the collection to be genuinely free per run, the endpoint is a fixed selector with no model in the loop at all, which is where a mature scrape usually ends up: authored with AI, running without it.
Legality and Etiquette
Any honest post on this topic has to include this section, and I am not going to pretend a tool setting resolves it.
The general shape most careful practitioners work to: respect robots.txt and the site's terms, prefer an official API when one exists, keep request rates low enough that you are not degrading the service for anyone else, and do not collect personal data you have no lawful basis to hold. IBM's treatment of the ethics here is genuinely good and worth reading in full rather than paraphrasing; the sentence I would carry away is that it is the responsibility of the practitioner to gather data ethically and in compliance with the relevant regulatory frameworks.
Two practical notes specific to the design in this post. First, a saved extractor that replays fixed steps is usually a lighter client than an agent that loads a page repeatedly while it decides what to do, so the efficient design is also the more considerate one. Second, if you self-host, the pages you fetch and the data you extract stay on your infrastructure, which matters when the collection touches anything sensitive. That is the main practical argument for an ai web scraping open source setup over a hosted endpoint: not cost, but that no third party holds a copy of what you collected.
Getting Started
If you take one thing from this post, take the sequence: let a model write the extractor, save what it wrote, and put a check on the output that is allowed to fail.
The fastest path is to open the Playwright node docs, build a three step version against a page you control, turn on Save steps for future, and watch the second run finish without a model call. Then add the row count condition before you schedule it, because the check is the part everyone skips and it is the part that makes the data trustworthy.
If you want the wider context on how this fits into a workflow rather than a script, what is AI workflow automation is the pillar, agentic workflows covers when to hand a decision to an agent at all, and the template library has runnable starting points. Heym is open source and self-hostable, so an ai web scraping python stack you would otherwise assemble from a browser driver, a scheduler, a queue and a database arrives as one canvas.
FAQ
What is AI web scraping?
AI web scraping is any setup where a language model helps get structured data out of a web page. It covers three quite different designs. In the first, an agent reads every page at run time and decides what to pull. In the second, a model writes a reusable extractor once and the extractor runs on its own afterwards. In the third, a fixed script does the navigating and a model is called only for the part of the page that has no stable structure. All three are marketed under the same phrase, which is unhelpful, because they have different accuracy, different costs, and different ways of going wrong.
How accurate is AI web scraping?
Less accurate than the category implies, and it depends heavily on the design. On WebLists, a benchmark of 200 data extraction tasks across four business use cases, language models with search reached 3% recall and state of the art web agents reached 31%. The system that converted its run into a repeatable program, built a generalizable CSS selector and replayed it, reached 66%. So the honest summary is that reading the page fresh on every run recovered under a third of the data, and turning the run into a program roughly doubled it.
How much does AI web scraping cost?
It depends on whether the model runs once or on every row. If an agent reads each page at run time, your cost scales with pages times runs, so a job over 5,000 products every day is 5,000 model calls a day forever. If the model writes the extractor once and the extractor replays, the model cost is close to a fixed setup charge and the recurring cost is just the browser. The WebLists paper measured this directly and reported roughly a threefold reduction in cost per output row for the replay design.
What happens when the website changes?
Two different things, and they are worth separating. A saved extractor whose selector no longer matches anything fails loudly, which is the good case, because you find out. A saved extractor whose selector now matches the wrong element keeps working and returns a plausible wrong value, which is the bad case, because nothing looks broken. Selector healing addresses the first. Only validation addresses the second, which is why a schema, a range check, and an alert on a suspicious result matter more than a smarter model.
Can AI web scraping handle pages behind a login?
Yes, and the reliable pattern is to reuse a session rather than to type a password on every run. Save the browser storage state after one successful login, restore it before the steps run, then check that a selector only a signed in user can see is actually visible. If that check fails, run a short fallback login and continue. This keeps credentials out of the step list for the ordinary case and still recovers automatically when the saved session expires.
Is AI web scraping legal?
It depends on what you collect, from where, and under which terms, and it is not something a tool can settle for you. The general shape most practitioners work to is: respect robots.txt and the site terms, do not collect personal data you have no basis to hold, do not send request volumes that degrade the service, and prefer an official API when one exists. As IBM puts it, it is the responsibility of the practitioner to gather data ethically and in compliance with the relevant regulatory frameworks. Treat automation features as a way to be a better behaved client, not as a way around an access control.
References
- Bohra et al., WebLists: Extracting Structured Information From Complex Interactive Websites Using Executable LLM Agents, arXiv:2504.12682, April 2025
- Kim, Kim and Jeong, NEXT-EVAL: Next Evaluation of Traditional and LLM Web Data Record Extraction, arXiv:2505.17125, May 2025
- Ferguson et al., ExtractBench: A Benchmark and Evaluation Methodology for Complex Structured Extraction, arXiv:2602.12247, February 2026
- xAI, Introducing Grok Bot, 11 August 2026
- IBM, What is AI Scraping?, December 2025
- Playwright, Locators
Written by Ceren Kaya Akgün, who works on the Heym execution engine. Heym is our own product, so treat the product sections as interested rather than neutral; the benchmark figures are from published papers you can check yourself, and the links go to the abstracts rather than to summaries of them.
Steps at a glance
- Decide whether the model runs once or every run. Write down how many pages the job touches and how often it repeats. If pages times runs is a large number, design for a saved extractor that replays. Reserve per run model reading for jobs that are genuinely one off or where the page layout is different every time.
- Add the Playwright node and fix the navigation. Create a workflow, add the Playwright node in Steps mode, and write the deterministic part by hand: navigate, any clicks or scrolls needed to reveal the data, then getVisibleTextOnPage or getText for the region you care about. Fixed steps cost nothing per run and cannot be redirected by the page.
- Use one AI step for the part that keeps moving. Add a single aiStep with plain language instructions and an LLM credential for the section you cannot express as a stable selector. Turn on Save steps for future so the generated actions are written back into the workflow, and turn on Auto heal mode so a failed selector is repaired instead of failing the run.
- Extract into a narrow schema, not a wide one. Send the captured text to an LLM node with JSON output enabled and a schema listing only the fields you will actually use. Make every field nullable and instruct the model to return null rather than guess, so a missing value stays visibly missing.
- Add a check that can fail. Put a Condition node after the extraction that tests something you know must be true: a row count above a floor, a price inside a plausible range, a required field that is not null. Route the failing branch to a notification so a silently wrong result becomes an audible one.
- Schedule it and watch the trend. Attach a cron trigger for recurring collection, send the clean rows onward to a sheet, a database, or a RAG index, and keep an eye on run duration and row counts over time. A steady drop in rows returned is usually the first sign that a page changed underneath you.
Build AI workflows without writing code.
Import ready-made AI automations directly into Heym — the source-available workflow platform.

Founding Engineer
Ceren is a founding engineer at Heym, working on AI workflow orchestration and the visual canvas editor. She writes about AI automation, multi-agent systems, and the practitioner experience of building production LLM pipelines.
Enjoyed this post? Get the next one in your inbox.
A monthly note with practical ideas for building AI workflows that hold up in production. No noise, and you can unsubscribe anytime.