Automate web forms with an AI form-filling API
Send a goal and a URL. An AI agent fills and submits forms in a real browser, signs in with 2FA, attaches files and asks before it submits. Pay per step.
Some web work has no API: a supplier portal, a quote form, a job application, an account page behind a login. The browser agent automates web forms like these from one API call. You describe the task in plain words and give a start URL. An AI agent works through it in a real Chromium browser: it fills the fields, signs in with secrets it never sees, attaches your files, waits for your approval before it submits, and returns the result as text and JSON.
Hand it to your AI agent
Copy this prompt into Claude Code, Cursor, Codex or any coding agent. It tells the agent where the docs are and how to use your API key.
Automate a web form or multi-step web task for me with the Lovely Router browser agent: a real browser that fills forms, signs in (including 2FA), attaches files and asks before it submits.
- Docs (read first): https://lovelyrouter.com/docs/browser-agent.md and https://lovelyrouter.com/docs/browser-agent/logins.md and https://lovelyrouter.com/docs/browser-agent/human-in-the-loop.md
- Start: POST https://lovelyrouter.com/v1/browser/runs with `{"goal": "...", "start_url": "...", "approve": "submit", "output_schema": {...}}`. Put every value the form needs in the goal. Poll the `poll` path; when it waits (`needs`), show me the fields and only reply `{"approve": true}` at .../reply after I say so.
- Never put passwords or codes in the goal: store them with PUT https://lovelyrouter.com/v1/browser/vault/<name> (`value`, `kind`, `origins`) and pass the names in `secrets`.
- Billed per step. Use it only on accounts I own or may use.
- Auth: read my API key from the LOVELY_API_KEY environment variable and send it as `Authorization: Bearer $LOVELY_API_KEY`. Never print or commit the key. If it is not set, ask me to create one at https://lovelyrouter.com/app/keys.
- Billing is prepaid: every call is charged to my balance, so test with a small request before running anything large.
- Every docs page is plain Markdown; the full index is https://lovelyrouter.com/llms.txt.
My task: <the site, what to fill in or do, and what proves it worked>How it works
Describe the task
Write the goal the way you would brief a careful assistant: every value the form needs, and what proves success ("tell me the confirmation number"). Start on the form itself when you know its URL.
The agent fills the form
Each step, the agent reads the page and does one action: click, type, choose an option, upload a file or fill a saved secret. Before it clicks a button that submits a form, it checks every field against your goal and fixes values that don't match.
You approve, it submits
By default the agent pauses before purchases, bookings, messages, deletions and applications, and shows you the form's values. You reply with an approval, and the run ends with an
answer, plusdatain your schema if you asked for one.
Fill and submit a form with one request
curl https://lovelyrouter.com/v1/browser/runs \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{
"goal": "Request a quote for 500 blue 750 ml water bottles with our logo, delivered to 12 Main St, Springfield, IL 62701 by December 1, 2026. Contact: Ada Lovelace, ada@example.com. Submit the form and tell me the quote reference.",
"start_url": "https://supplier.example.com/quote",
"approve": "submit",
"output_schema": {"quote_reference": "string", "confirmation_message": "string"},
"webhook": "https://api.example.com/hooks/browser"
}'The request returns 202 at once and the agent works in the background. With "approve": "submit" it stops before the submit button, and your webhook gets a signed run.waiting event whose needs holds a prompt for a person, the form's values in fields, the button label in action and a screenshot. Approve it:
curl https://lovelyrouter.com/v1/browser/runs/brun_5b7d9f1a3c5e7a9b1d3f5a7c/reply \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{"approve": true}'The agent clicks the button and finishes; run.finished arrives with the answer and the JSON in data. Reply {"approve": false, "reason": "Wrong address"} instead and the agent doesn't submit: it reads your reason and tries another way or reports why.
Logins and two-factor codes
Store each credential once with PUT /v1/browser/vault/{name}: its value, a kind (password, username, text or totp) and the origins where it may be typed. Pass the names in the run's secrets. The model only sees names like portal_password; the value is typed only on a site you allowed, so a lookalike login page can't get it.
Store the TOTP seed as a totp secret and the agent types the current 6-digit code.
The agent pauses with a question, and you reply {"secret": "481923"}. It types the code without seeing it.
Add save_profile to a login run, then start later runs with profile to skip the login.
Pass ephemeral_secrets for a credential that should live only for one run; it is deleted when the run ends.
Everything a form workflow needs
Write-only vault, TOTP codes, saved sessions.
Questions, approvals, CAPTCHA handovers and takeovers.
Upload once; the agent picks the right file for each field.
Signed events when a run waits for you or finishes.
Stream each step and the browser's screen.
Confirmation numbers and totals as JSON.
Recipes
Upload a CV and a cover letter with PUT /v1/browser/files/{name}, pass both in files, and say in the goal which one goes where. The agent matches each upload field to the document's purpose, not just its file type.
Set a webhook, forward run.waiting approvals to your team's chat, and post their answer to the run's reply path.
Start from a saved profile, pass the secrets too so the agent can sign in again if the session expired, and ask for the latest invoice total in an output_schema.
For forms you trust it to submit on its own, such as logging hours in an internal tool, set "human": false and "approve": "none". The run then reserves nothing for waiting time.
To watch a run, add "stream": true, "screen": true and get each step and the browser's screen as it happens. When a page shows a CAPTCHA, the agent hands you a Live View link; you solve it, reply {"done": true}, and it carries on. Use the agent only on accounts you own or are allowed to use; the Acceptable Use Policy has the details.
What you pay
You pay per step: $0.006 in fast mode, $0.012 in accurate mode for date pickers, maps and custom widgets. The models are included and there is no run fee. A login takes 4 to 8 steps; a long multi-page form takes 15 to 25. Each step includes one minute; waiting longer for a person costs $0.005 per minute, and pauses themselves are not billed as steps. A run holds max_steps times the step price plus one wait up to human_timeout_minutes, then settles to what it used. A run that fails or that you stop pays for the steps it took. See pricing, and the browser agent page for the benchmark.
Frequently asked questions
Can an AI fill in forms behind a login with two-factor authentication?+
Yes. Store the password and the TOTP seed as vault secrets, and the agent signs in and types the current 6-digit code. For codes sent by text or email, it pauses and you reply with the code.
Does the model see my passwords?+
No. The agent works with secret names, and each value is decrypted only when it is typed into a matching field on a site you allowed. Any secret value of six characters or more is scrubbed from page text, answers, data and the step trace.
What happens when the site shows a CAPTCHA?+
The agent can't solve CAPTCHAs. It hands the browser to a person through a Live View link, valid for one hour, and continues once they reply that they are done.
Can I make it wait for my approval before submitting?+
Yes. The default, approve "risky", pauses before purchases, orders, bookings, messages, deletions and applications. Set approve to "submit" to pause before every submit, or "none" to let it submit on its own.
Can Claude Code or another agent fill forms with it?+
Yes. The MCP server exposes the browser agent API as browser_run, browser_status, browser_reply and browser_takeover. Agents pass vault secret names, never the values.
For reading data rather than submitting it, see web data extraction; the full API is in the browser agent docs.