← All AI Engineer talks

AI Engineer World's Fair 2026

The Dark Arts of Web Automation: Teaching Agents to Use Websites Like Humans

Read the talk

Teaching Browser Agents to Sense, Act, and Verify

Corey Gallon builds browser automation around reusable code, CDP input, and a verification loop, reserving model calls for the steps that actually need judgment.

From a talk by Corey Gallon

Before you start: Familiarity with browser JavaScript, DOM events, and the distinction between model decisions and tool execution will help you follow the examples.

An account warning before the first demo

While preparing his browser-automation demonstrations, Corey Gallon received what he describes as an OpenAI account-ban warning for cyber abuse. The work behind the warning was a set of agents solving browser challenges without a human in the loop.

Dark slide with the opening claim in white and “ban me” highlighted in red; the speaker appears at lower left.
The opening claim: “OpenAI threatened to ban me for preparing this talk.”

The practical ambition is more familiar than the opening suggests: book things, send emails, and fill in forms. An agent can understand those tasks and still fail when a website rejects its interactions. Gallon’s premise is that driving Chrome through the Chrome DevTools Protocol gives the agent access to the browser’s own input machinery. He describes that as making an agent resemble a person with a mouse; whether an entire website can distinguish automation is a broader question than how a click enters Chrome.

The implementation has three parts: a programmable shell CLI, CDP access through his Chrome Agent tool, and an interaction loop that escalates through increasingly human-like techniques. The CLI captures repeatable work; CDP supplies perception and control; the loop decides whether an action actually accomplished anything.

0:290:42
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:29 · section reference included

Keep the model out of repeatable steps

Gallon starts by choosing shell tools over a model-mediated MCP workflow. His first point is that task capability need not decide the choice: he cites roughly 83% success for both CLI and MCP in an Arize evaluation. That evaluation used Opus 4.6 through the Claude Agent SDK on 25 GitHub tasks, with five repetitions per arm and LLM-judged correctness. Its results concern that task set, rather than browser automation.

A successful sequence should become a program. Once the steps are known, a shell command can replay them without asking a model to choose every next operation. Gallon contrasts that with an interaction pattern in which the model sits between successive tool calls. Reuse then improves both latency and the amount of information that must pass through the model.

Gallon reports seven CLI turns in under one minute versus 71 round trips and eight minutes for MCP on the same task. In the underlying Arize article, the task is milestone average time-to-close analysis, and the 71-call result is the MCP arm’s worst run—not an average. Only three calls in that run were actual MCP calls; the rest were bash parsing. The useful lesson is about how the work was organized: repeated model decisions and intermediate-data handling can dominate the task.

Gallon also attributes an up-to-75× token-cost advantage to CLI use. The matching Anthropic code-execution example reduces token usage from 150,000 to 2,000 by combining selective tool loading with code execution using MCP. It supports the value of moving deterministic work into code, but not a general CLI-versus-MCP price ratio. MCP itself does not require a model round trip for every operation. That distinction preserves the architectural point: batch predictable operations, and spend inference on decisions.

2:402:56
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

2:40 · section reference included

See, hear, and operate through CDP

Chrome’s familiar F12 DevTools panel is an entry point to the same protocol an agent can use. Chrome Agent exposes CDP and helps agents write code that replays browser interactions. Gallon describes the protocol at the time of the talk as having 57 domains, with hundreds of methods and events, which he groups into eight explanatory buckets. The surface changes frequently; the important design choice is to use a small working subset rather than make the agent reason over the entire protocol.

That subset gives the agent several different ways to understand a page:

CapabilityBrowser channelsWhat they provide
SeeDOM, accessibility tree, screenshotStructure, semantics, pixels
HearNetwork traffic, console, logsRequests, responses, diagnostics
OperateClicks, keystrokes, navigationChanges to browser state

These channels are complementary. The DOM can expose a control’s structure, the accessibility tree can explain its role, and a screenshot can show what is actually visible. Network and console observations add evidence that the page responded to an action.

Slide titled “See. Hear. Operate.” with three columns listing browser structure, network and console information, and interaction controls.
CDP capabilities organized into “See,” “Hear,” and “Operate.”
4:104:19
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

4:10 · section reference included

Verify each move before climbing the ladder

The basic loop is deliberately small:

  1. Sense: inspect the current page through one or more available channels.
  2. Act: perform one interaction, such as clicking, typing, or selecting.
  3. Verify: observe the result through a different channel.

A click returning successfully is not evidence that a purchase entered the cart or a message was sent. After clicking, inspect the screen or the resulting network activity. Then start the next iteration from the state that actually exists.

When the expected change does not appear, Gallon climbs his three-rung interaction ladder. The rule is to use the lowest rung that works:

RungInteraction techniqueReason to use it
OneIn-page APIs or synthetic JavaScript clicksThe page accepts direct programmatic interaction
TwoBrowser input through CDP’s Input domainSynthetic events are rejected
ThreeVision and human-like interaction behaviorLocating or operating the control requires more

Rung one is the inexpensive default. Rung two changes how input reaches the page. Rung three adds capabilities such as interpreting pixels, following a mouse path, pausing, or varying movement. Escalation follows failed verification, rather than starting every task with the most elaborate technique.

Exploration and execution are separate phases. First, work through the loop manually, climbing only until the task succeeds. Then preserve the working path as code, an agent skill, or both. Code records the repeatable interactions; a skill can retain the instructions needed to use them. The next run should benefit from the previous discovery.

5:395:55
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

5:39 · section reference included

Outlook: generate the message, replay the interactions

Before the demonstrations, Gallon returns to the lawyer from his opening. He says the examples come from real browser-agent experience, but everything shown runs on infrastructure he owns and accounts he operates. That scope matters for the increasingly adversarial browser challenges that follow.

The first task is ordinary office work: send a batch of personalized emails through Outlook’s web client. The compose window accepts rung-one interaction. A synthetic click opens it, code fills the fields, and another synthetic click sends the message. Once that sequence is captured, a program can loop over recipients from one command. Gallon uses twenty or two hundred emails as examples of reusing the same sequence.

The model still has a job: personalizing the content. It does not need to rediscover how to open the composer or fill the subject field for each recipient. Content generation varies; browser mechanics repeat. The frame pairs the recipient loop with an Outlook message list and reading pane, showing those two responsibilities together.

Slide titled “Outlook — batch send,” with a recipient loop on the left and an Outlook message list and reading pane on the right.
Outlook batch-send pseudocode beside the running browser demonstration.

Why use the web interface instead of a mail API? In Gallon’s corporate scenario, app registration and administrator approval put API access beyond an employee’s reach, while an existing web login already lets that employee send mail. The Microsoft Graph permissions reference distinguishes application Mail.Send, which requires admin consent, from delegated Mail.Send, which does not inherently require it; tenant policy can still constrain access. The example is therefore about a particular access barrier, not a universal requirement of Office 365.

Gallon calls the resulting web interface a universal, or permissionless, API. Here, that means avoiding a separate API integration while using the access of an authenticated account. It does not grant permissions beyond that account’s existing access.

8:298:43
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:29 · section reference included

Demazon: a successful click can change nothing

The next demonstration moves to a mock retailer, Demazon. The synthetic JavaScript click that worked in Outlook now does nothing to the Add to Cart button. There is no error: the page quietly ignores the event because it is untrusted. This is precisely why the loop needs verification beyond the action’s return value.

The relevant browser property is Event.isTrusted. It distinguishes browser-dispatched events from script-dispatched ones; HTMLElement.click() produces an untrusted click. It is not proof that a human caused the event. A small JavaScript example makes the distinction observable without involving a shopping site:

javascript

const button = document.createElement('button');
button.textContent = 'Inspect click trust';

const output = document.createElement('pre');
document.body.append(button, output);

button.addEventListener('click', (event) => {
  output.textContent += `isTrusted=${event.isTrusted}\n`;
});

button.click();

The programmatic call records isTrusted=false. Clicking the displayed button yourself records a browser-dispatched event. The flag describes event provenance, not the absence of automation elsewhere in the session.

Gallon then moves to rung two and uses CDP’s Input domain. In the demonstration, the resulting trusted click is accepted and the item enters the cart. That establishes the difference for this page’s event check, rather than proving that all bot detection has disappeared. The lower panel illustrates what the page’s logs might look like; it is not a retailer’s internal log feed. The visible cursor is also an added visualization of CDP input, not Gallon’s physical mouse moving across the screen.

10:5110:59
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

10:51 · section reference included

Turnstile: visible does not mean selectable

Rung three begins with Cloudflare Turnstile. In Gallon’s demonstrated setup, the apparently simple checkbox is difficult to reach through ordinary page scripting. He describes three isolation boundaries: a closed shadow root, a cross-origin iframe, and another shadow root. The obstacle is initially locating and reaching the control, rather than interpreting a complicated visual puzzle.

His approach changes from selecting the checkbox as an element to locating it on the rendered page. The demonstration uses the iframe’s screen location and the checkbox’s relative position, then lets Chrome route a trusted coordinate interaction. Gallon reports completion without a human in the loop. The next challenges add another requirement: the agent must interpret what it sees, not merely reach a visible control.

12:4412:59
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

12:44 · section reference included

MTCaptcha and Lemin: perception and movement

MTCaptcha presents noisy characters. The agent takes a screenshot, uses its own vision capability to read the text, and enters the answer through trusted keyboard input in the cross-origin widget, one character at a time. The demonstration ends with server verification and token issuance. Recognition, input delivery, and confirmation are distinct steps: seeing the answer alone does not finish the task.

The next example, Lemin, is a jigsaw puzzle: identify the missing piece’s destination and drag the piece into the gap. Unlike the preceding isolation problem, Gallon says this example has neither a shadow root nor a cross-origin iframe. The piece is accessible in the page. The difficulty lies in the drag.

Gallon explains that this class of challenge samples a trail of mouse positions, including variation in speed and jitter. The demonstrated movement eases in, follows a slight curve, deliberately overshoots, and settles back into place. Vision supplies the destination; movement supplies the interaction behavior. His “moves like Jagger” joke captures the distinction: solving the geometry and satisfying the movement check are different problems. Turnstile, MTCaptcha, and Lemin have now exercised three different capabilities—reaching an isolated control, reading an image, and operating a control with a trajectory.

14:2614:39
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

14:26 · section reference included

reCAPTCHA v2: split the driver from the visual judgment

The last demonstration is reCAPTCHA v2: a checkbox followed by a blurry image grid asking for objects such as crosswalks or traffic lights. This combines the earlier capabilities into a system with two responsibilities, which Gallon calls the solver and the operator.

The solver is deterministic code. It handles the initial checkbox interaction, reaches the challenge iframe, captures the grid each round, and restarts when a round expires. Those operations do not require a model to choose each next click. The unresolved step is visual: deciding what the grid contains—for example, whether a tile shows a bus.

That decision belongs to the operator. The solver supplies the grid; the agent selects the matching tiles and returns its answer; the solver resumes the browser work. Between rounds, the agent waits.

ComponentResponsibilityModel involvement
SolverBrowser driving, screenshots, round handlingNone for deterministic steps
OperatorInterpret the grid and select tilesVisual judgment per round

The boundary is the important part. The model receives the decision that requires perception, while code retains control of the repetitive interaction sequence.

16:3616:41
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

16:36 · section reference included

Latency becomes a correctness constraint

During playback, Gallon remarks that the agent spotted bicycles he had missed in some tiles. He reports that the completed solution is verified by the server. The selected frame shows an intermediate bicycle grid with a tile checked, beside the explanation of expiring rounds.

A reCAPTCHA bicycle grid with one tile checked, beside text about expiring rounds and the cost of a model call on every step.
A bicycle image challenge beside the explanation that each round expires.

Speed matters because, in Gallon’s account, each image round expires and one challenge can contain several consecutive rounds. Calling a model for every look and click consumes the available window before the interaction sequence finishes. His successful design instead uses deterministic browser code with one quick visual judgment per round. Google’s documented two-minute validity period applies to an issued response token, not to the duration of each image-selection round.

This is where the early CLI argument becomes consequential: fewer model round trips can determine whether the task finishes in time, not merely whether it feels responsive. The relevant architectural property is programmable execution between model decisions. Gallon describes his solution as repeatable and reliable, but supplies no trial counts or measured success rate for that claim.

18:3018:44
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

18:30 · section reference included

Turn exploration into a reusable tool

The CAPTCHA demonstrations serve as stress tests for the engineering method. They expose different reasons a browser interaction can fail, then show why an off-the-shelf agent benefits from carefully chosen sensors, explicit verification, and reusable execution code. The durable result of exploration is a recorded solution: a programmable tool that uses the browser’s observations, checks whether actions landed, and escalates only when the simpler technique fails.

The opening account warning also gets a resolution. Gallon says OpenAI rescinded the threat after a conversation, leaving him with access to Codex. Chrome Agent, his daily tool for this work, is installable through the Python ecosystem. He also explicitly encourages building your own: the method does not depend on adopting his particular implementation.

19:5120:09
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

19:51 · section reference included

Resources

From the talk

  • The speaker’s written companion to the talk, covering the verification loop and three-rung interaction ladder.

  • Code execution with MCPArticle

    Explains selective tool loading, processing intermediate results in code and composing MCP operations without a model call for each step.

  • The normative definition of Event.isTrusted and the distinction between browser-dispatched and script-dispatched events.

Read the complete timestamped transcript
  1. 0:00

    [upbeat music] All right. The dark arts of web automation.

  2. 0:18

    That sounds ominous, right? [laughing] It sounds like something I'm gonna teach you that you're going to need a lawyer for. Uh, well, actually, we'll come back to the lawyer in a minute, but a little bit of background.

  3. 0:29

    As I was preparing for this talk, OpenAI threatened to ban my account just for the work that I was doing in preparing for the talk. [dramatic music]

  4. 0:42

    So I checked my inbox a few days ago and got this, and that's a real shocker, right? So what does one do to earn the ban hammer for cyber abuse with a web browser?

  5. 0:59

    Well, this. I was doing this. So what you see here is every one of these is being solved by an AI agent with no human in the loop.

  6. 1:12

    And in fifteen minutes or so, you'll understand exactly how this is possible.

  7. 1:18

    I want my agents to be able to use the web exactly the way that I do. I want them to book the things, to send the emails, to fill in the forms so that I don't have to.

  8. 1:30

    But the moment that something isn't a person starts clicking into a page, web pages often fight back. So this talk is about winning that fight, and it starts with one slightly unconventional idea.

  9. 1:45

    And here it is. This is the premise of the whole talk on one slide. A CDP browser is just like a meat bag with a mouse.

  10. 1:56

    No joke. Well, at, at least as far as Google and Cloudflare and the rest can tell. No joke. If you have a browser dr-- an agent driver browser using the Chrome DevTools Protocol,

  11. 2:08

    your agent's clicks and keystrokes travel the exact same path inside Chrome that yours do,

  12. 2:15

    and that's the big idea. The rest of the talk is about how to pull it off, and that comes down to three things.

  13. 2:22

    To-- You need a, a CLI, not an MCP, the Chrome DevTools Protocol, which is where a tool that I wrote called Chrome Agent comes into play, and then a loop run on a ladder.

  14. 2:37

    So let's start with the one that picks a fight.

  15. 2:40

    The first thing is to give your agent a CLI and not an MCP server, and by CLI, I mean shell-based tools. Before you in the back knuckle up on this one, there are some specific reasons as to why this is necessary.

  16. 2:56

    First of all, it's worth noting that capability is a wash. So in a recent study by the guys at Arize AI, both a CLI and an MCP, given the same task, achieve those tasks successfully roughly eighty-three percent of the time.

  17. 3:10

    However, a CLI beats MCP in reuse, in speed, and in cost. So let's take reuse first. A CLI sequence can be programmed. You write it once, and you run it a thousand times without a model in the loop, whereas MCP hits the model on every single turn.

  18. 3:32

    The CLI is faster for a similar reason, because there's not a model in the middle of every step. So in that same study that I mentioned before, MCP took seventy-one round trips and eight minutes for the same task that took a CLI only seven turns and in under one minute.

  19. 3:50

    So hold on to speed because that actually comes back at the end. Lastly, token cost. Anthropic themselves reported that the CLI can be as much as seventy-five times cheaper in terms of token cost.

  20. 4:06

    So what is it that we're actually running on the command line?

  21. 4:10

    We drive the browser in the Chrome DevTools Protocol, and that's the second thing that your agent needs to appear human. You already know this protocol, even if you don't know its name.

  22. 4:19

    That panel that pops up when you hit F twelve, that drives the browser using exactly this protocol. Your agents can speak it too. They can use the Chrome Agent tool.

  23. 4:30

    And Chrome Agent also makes it really easy for your agents to write code to replay CDP interactions. The surface area of CDP is enormous, and it changes really frequently.

  24. 4:42

    So as of now, it's fifty-seven domains, and within those, there are hundreds and hundreds of methods and events. So I've kind of bucketed all of the domains into eight buckets to make it a little easier to keep it in your head.

  25. 4:55

    But no worries, you don't actually need all fifty-seven domains. In order to interact with a browser in the way that a human does, you need a small subset of these.

  26. 5:04

    And the best way to think about that small subset is in terms of the digital senses that they give your agent. So you see the page. You may read its structure from the DOM.

  27. 5:17

    You may read its semantics from the accessibility tree, or just take a screenshot if you need the pixels. You hear the page, so that may be network traffic to and from, uh, or co-- the console or logs.

  28. 5:32

    And then you operate the page with clicks and with keystrokes and with navigation.

  29. 5:39

    The third and final thing that you need for your agent to appear human is what I like to call a loop on a ladder. So here's the loop: sense, act, verify, and you repeat that until the page gives in.

  30. 5:55

    So in sensing, we perceive the page through one or more channels, the DOM, the accessibility tree, a screenshot, as I just mentioned, and then you act. You do one thing.

  31. 6:05

    You click something, you type something, you take a scr- you, uh, select something, and then you verify. And now this is sensing again, but it's sensing through a different channel than the interaction.

  32. 6:17

    So, for example, if you've clicked something, don't ask the click if it was successful, check the network or check the screen. So you sense where you are, you make one move, you confirm that it landed, and then you iterate again.

  33. 6:33

    And when the loop won't close, so you sense, act, verify, and the page still won't do what it is you're trying to do, that's the page fighting back. And so that's telling you to climb the ladder.

  34. 6:45

    The meat bag ladder, that is. This is a ladder of techniques that are increasingly more human as you climb it. It has three rungs, and you climb only as high as the page forces you.

  35. 6:57

    Or said differently, you, you climb to the lowest ladder that... uh, the lowest rung, sorry, that actually works. So on rung one, you don't act human at all. If you can just use the API that's exposed within the page, then, then issue a synthetic JavaScript click, then do that.

  36. 7:15

    It's easy, it's free, it's instant, and it's the right default. You climb to rung two when faking it stops working, so when you need to use a real click, for example, using the CDP Input domain.

  37. 7:31

    Now, this is agent input that the page cannot tell apart from your own.

  38. 7:37

    You climb to rung three when you need human input and human behavior. So this is a real mouse path, maybe with a, a little dwell and some jitter, uh, or vision to actually see and interpret things.

  39. 7:52

    So you start cheap, you climb run- one rung at a time, only when the page makes you. Climb the ladder, loop on each rung, and then write down the path that worked.

  40. 8:04

    And that's how you arrive at fully automated AI agent-driven browsing. First, you explore. You run the loop by hand. You climb rungs until you... the thing actually works, and then you automate.

  41. 8:18

    You write the solution down so you never have to figure it out again, and you write it down as code or as an agent skill, or very often, as both.

  42. 8:29

    So let me show you how this all comes together but, first of all, with a word from my attorney. So I mentioned that the lawyer would be back, and everything you're about to see is, in fact, real agent browser use in the wild.

  43. 8:43

    It's taken from real experience. However, upon the advice of counsel, everything that you're seeing is running only on infrastructure that I own and accounts that I operate. Right, now, so who's ready to see the agents get busy with the browser? [audience applauding]

  44. 9:01

    All right. So here's a simple one, everyday use case we'll start with. Let's send a batch of personalized emails, each one different, from your Outlook web client. We've got some lovely pseudocode on the right side...

  45. 9:16

    oh, sorry, left side. It's inverted. Left side of the, uh, the, the slide that makes it really simple for you to see how it all kind of works in code.

  46. 9:25

    Outlook's compose box has nothing for us to defeat, so this is rung one of the meat bag ladder. You don't act human at all. A synthetic click opens the compose window.

  47. 9:35

    We fill this in programmatically, and another synthetic click sends it.

  48. 9:40

    And then you let that rip, right? So the reason this is going so smoothly is it's executing a program. So you capture the sequence once and then loop it, whether it's twenty emails or two hundred, and

  49. 9:54

    from, from just that one command. So you solve it once and reuse it forever.

  50. 10:00

    The agent is riffing on content to personalize it here as we go, but it's running a program to drive all of the interactions. Now, you may ask, "Why would we drive the web UI at all?"

  51. 10:13

    Like, why not just use the API? And in corporate environments, the API for an Office 365 tenant requires an app registration, and it also requires admin approval, which, as an employee, you can't often get.

  52. 10:29

    And so in this pattern... Well, sorry, whereas the, the web login you have is all you need to be able to do exactly what you see on the screen here now.

  53. 10:36

    And so in this pattern, the web UI itself kind of becomes a universal API, right? Like a permissionless API. Which is really neat. So that's rung one, but what happens when the page starts fighting back?

  54. 10:51

    So let's say that you're browsing on your favorite online mega store, and we'll just call them Demazon. [audience laughing]

  55. 10:59

    So they're a crafty bunch over there at Demazon, and they have no love for your bots at all. Now, if you take that same JavaScript click that just worked in Outlook and you point it at, say, the Add to Cart button, you get nothing.

  56. 11:15

    Literally nothing. There's... They've no failure, there's no error, just nothing happens. And the page is ignoring it. And the reason for that is the page is checking, "Was this click from a human source?"

  57. 11:29

    Chrome stamps every single event with just that answer, whether it's trusted or untrusted. So the JavaScript click that we fired previously is stamped untrusted, and in this case, the page just quietly drops that input.

  58. 11:45

    But that's no worries. We'll just climb the meat bag ladder. So we move to rung two, and we click using Chrome's Input domain, and that uses the exact same input path that your actual mouse uses, and now it's stamped trusted, and the page can't tell the difference between your mouse and our agent, and bam, the item's dropped

  59. 12:06

    straight into the cart. So we've got quite the inside view of demazon.com here. So if you look at this lower panel, you can imagine that this is what the page's logs look like.

  60. 12:17

    Every one of the untrusted clicks fails, but the trusted ones go through, no worries. Now, as a heads-up going forward, when you see this mouse cursor moving here, that is added programmatically just so that you can visually see the mouse inputs that the agent is giving to the browser using Chrome Agent and CDP.

  61. 12:38

    It's not actually moving my mouse here. All right.

  62. 12:44

    Rung two is where the real meatbag inputs begin, but that's not enough to replace you in the browser. So we climb to the top of the meatbag ladder, rung three, and this is the narrow frontier where pagers are actively hunting for bots.

  63. 12:59

    There are a variety of techniques that we're gonna deploy here, though, so let's talk through a few of them. I'm sure this guy looks familiar, right? This is Cloudflare Turnstile.

  64. 13:10

    It looks deceptively simple, but it is the hardest target that we've hit yet, [lip smacks]

  65. 13:16

    and it's because that little checkbox can't be easily reached through typical web automation programming. Because these cheeky guys have hidden this thing through three isolated boundaries. First, it's encapsulated beneath a closed shadow root, and then the whole widget itself lives in a cross-origin iframe, which in it then also has another shadow root. [lip smacks]

  66. 13:41

    So to every cheap trick, that, that checkbox is unclickable. There's no element to grab. So what do we do? Well, we just stop trying to grab it, right? [chuckles] We ask the browser where it is that the iframe sits on the screen.

  67. 13:57

    We do a little bit of math to figure out where the checkbox is, then we fire a trusted click right at that position on the glass, and then Chrome does the rest for us, right?

  68. 14:08

    A real click lands right in the checkbox, and we're off and running. There's no human in the loop. This is all agent. So that's level one cleared, and the trick here was really just kind of figuring out how to interact with it.

  69. 14:21

    But all the next levels now make you prove that you can actually see.

  70. 14:26

    So this is MT CAPTCHA. You remember this guy? And th-these guys are... And like it, they're, they're still around. Um, your agent's actually gotta read this guy. And so what the agent does is simulate what you would do.

  71. 14:39

    It takes a screenshot of the challenge, looks at it, and then uses its own vision capability to pick the characters out of the noise. Then it types the answer back using real trusted keystrokes routed into the widget's cross-origin iframe

  72. 14:58

    one character at a time, and these are the same keyboard inputs that you would send. And then the server agrees. The text is verified, and the token is issued.

  73. 15:08

    Now, there's one more level before the final boss, and this one is won or lost based on how it is that you move like a meatbag.

  74. 15:17

    So this is by Lemon. Uh, it's a little jigsaw puzzle where you spot where the piece belongs and then you drag it in to fill the gap, and there's an entire class of CAPTCHAs just like this.

  75. 15:29

    Now, this one's tricksy in different ways. There's no shadow root. There's no cross-origin iframe. The piece is sitting right there in the page. The hard part here is the drag itself.

  76. 15:40

    So when you drop the puzzle piece, these types of CAPTCHAs sample the mouse movement into a trail of points the whole way, and so that includes jitter and changing speeds and all of that.

  77. 15:53

    So it's not just solving the puzzle, but it's solving it with moves like Jagger. So the agent drags the exact same way that a hand would drag, right? If you kind of watch him move, it eases in gently.

  78. 16:06

    There's, like, a slight curve. It actually deliberately overshoots the puzzle piece and then eases it right back in, [sniffs]

  79. 16:13

    just like a meatbag with a mouse. And it's using vision to identify the gap and then human-like motion to cross it. So that's Turnstile, that's MT CAPTCHA, and that's Lemon.

  80. 16:29

    Three gates built to keep agents out, and we've just beat each one of them, which leaves only one boss standing.

  81. 16:36

    And here he is, the final boss of the internet,

  82. 16:41

    reCAPTCHA v2. It's that little checkbox and then the blurry grid with, like, fuzzy pictures of crosswalks or traffic lights in it. We've all squinted at these ones. But we've got the whole kit now on how to beat this guy, too.

  83. 16:56

    The digital senses, the loop to deploy them in, the meatbag ladder, everything that you need to take down this cheeky bastard, so let's go. This is the whole machine, and it comes in two halves.

  84. 17:13

    On one side, we have the solver. This is pure code, no agent, no model. It does everything programmatically. It does the trusted click in the checkbox. It pierces into the, uh, challenge iframe, and in every round, it screenshots the grid, and if for some reason a round expires, it just re-arms itself and goes again.

  85. 17:33

    All of that, that bit there, is deterministic, it's fast, and it's free. [clears throat]

  86. 17:38

    But there's one step in the loop that the code can't do, and that's look at that grid of fuzzy tiles and figure out what it is that's in it.

  87. 17:46

    Is this a bus, for example? That's vision and thinking, and that needs eyes and a brain. And so that's the only thing that we give the agent as a job.

  88. 17:56

    We call that bit the operator. The solver taps the agent on the shoulder, and the agent takes one look at the grid, picks the tiles with whatever the thing is that we're looking for in them, hands that answer back to the solver, and then just hangs out waiting until the next lap.

  89. 18:13

    And this is really the entire talk running as one system. Code does the deterministic driving, and the agent does the only bits that require eyes and a brain. All right, who wants to see it go?

  90. 18:30

    There it is. So while this is playing, by the way, kind of have a look. Like, some of these are really hard. [laughs] Like, the, the agent was able to spot bicycles in some of these tiles that I didn't see.

  91. 18:44

    But ultimately, it's solved, it's verified by the server, and it's fast. And fast is the whole game here because this big, bad boss is on a clock. Every round expires, and one challenge can be multiple rounds back to back.

  92. 19:03

    An agent that round-trips a model on every click and on every look burns that clock and loses. The challenge expires well before it ever finishes. The only thing that I've found that defeats this whole mess is exactly what you're looking at here, deterministic code running at machine speed with one quick AI look per round.

  93. 19:25

    So remember when I told you to hold onto speed? This is exactly why, and this is also why this had to be a CLI running the CDP and not a model sitting in the middle of every single interaction.

  94. 19:38

    By the way, in case you're wondering, this wasn't a fluke. It's a repeatable, reliable solution now for solving this and, and other forms of CAPTCHAs. But here's what I want you to really walk out of here with.

  95. 19:51

    The big takeaway is the methodology that enabled this. The CAPTCHAs themselves were just tricksy little tests that demonstrate the methodology. This came down to careful, disciplined engineering, and the engineering enabled the agent to do something that it could not do at all off the shelf.

  96. 20:09

    And the method is simple. Give your agent a CLI so that you can program it, drive the whole browser through CDP using its digital sensors, run it as a loop on the meat bag ladder, and climb only as high as the page forces you to, and then explore until you solve it and write the solution down.

  97. 20:30

    That's what makes this durable and useful. You figure it out once, and you do it forever, which brings us all the way back to the good folks at OpenAI.

  98. 20:40

    After a quiet word, they kindly rescinded the threat, so I've still got access to Codex, which is nice.

  99. 20:48

    So you too can use Chrome Agent. It's installable in the Python ecosystem. That's the tool that I wrote that I do all this with, and I use it all day, every day.

  100. 20:57

    Or frankly, build your own, right? Like, I'm not here shilling a product. Uh, we live in the age of unbounded personalized software. Please, however, do follow me on X.

  101. 21:06

    I'd love to chat to you and learn how it is that you're automating the web with AI. And if you'd like to chat more about it, I'll pop out there into the, uh, huddle space, and we can have a chat now, but happy hacking. [audience applauding] [outro music]