Skip to main content
Automate form submissions using cloud browsers that handle dynamic content, authentication, and bot protection. Browserbase gives you reliable infrastructure for form filling workflows, whether you’re using Stagehand or Playwright.
Looking to deploy form automation as an API? Functions let you package form automation workflows as cloud functions that can be invoked via webhook or API call—perfect for integrating form submissions into your applications.

Implementation

1

Create a session

Create a Browserbase session and authenticate if needed. Use browser contexts to persist authentication across pages.
2

Navigate to the form

Go to the target page and wait for form elements to fully load before interacting with them.
3

Fill form fields

Identify and populate form elements (text inputs, dropdowns, radio buttons, and checkboxes) with your data.
4

Submit and verify

Trigger the submit button and check for success messages or validation errors.

Template

Get started quickly with a ready-to-use form filling template.

Form Filling

Clone, configure, and run in minutes

Example: Automating a Google form

To demonstrate how to automate form submissions using Browserbase, you can use a sample Google Form designed specifically for this tutorial: Google Form This form collects responses in various formats:
  • Text input
  • Radio button
  • Checkboxes

Code example

import { Stagehand } from "@browserbasehq/stagehand";
import { z } from "zod";
import dotenv from "dotenv";

dotenv.config();

async function main() {
	const stagehand = new Stagehand({
		env: "BROWSERBASE",
        verbose: 0,
	});

	await stagehand.init();
	const page = stagehand.context.pages()[0];

	async function fillForm(inputs: any) {
		// Navigate to the form
		await page.goto("https://forms.gle/f4yNQqZKBFCbCr6j7");

		// Select the superpower radio button
		await stagehand.act(`Select the superpower: ${inputs.superpower}`);

		// Select the features used checkboxes
		await stagehand.act("Select the features used: " + inputs.features_used.join(", "));

		// Fill in the coolest build text field
		await stagehand.act("Fill in the coolest_build field with the following value: " + inputs.coolest_build);

		// Submit the form
		await stagehand.act("Click the submit button");
		await page.waitForTimeout(5000);

		// Extract to log the status of the form
		const status = await stagehand.extract({instruction: "Extract the status of the form", schema: z.object({status: z.string()})});
		console.log(status);

		await stagehand.close();
	}

	const inputs = {
		"superpower": "Invisibility",
		"features_used": [
			"Verified",
			"Proxies",
			"Session Replay"
		],
		"coolest_build": "A bot that automates form submissions across multiple sites.",
	}
	
	await fillForm(inputs);
}

main().catch(console.error);
This example form is for testing purposes - feel free to submit responses multiple times while experimenting.

Best practices

Wait for form elements to load

Target specific form elements with waitForSelector rather than using arbitrary timeouts. This ensures your automation proceeds only when the form is ready.
// Wait for a specific input field to appear
await page.waitForSelector('input[name="email"]', { timeout: 10000 });
await page.fill('input[name="email"]', "user@example.com");

Handle multi-step and dynamic forms

Forms that reveal fields based on previous selections need sequential interaction. Wait for each new section to render before continuing.
// Select an option that reveals additional fields
await page.selectOption('select[name="account_type"]', "business");

// Wait for the dynamically revealed fields
await page.waitForSelector('input[name="company_name"]', { state: "visible" });
await page.fill('input[name="company_name"]', "Acme Corp");

Persist authentication with contexts

Use browser contexts to save login state across form automation runs, so you don’t need to re-authenticate each time.
const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
const session = await bb.sessions.create({
  browserSettings: {
    context: { id: "my-form-context", persist: true },
  },
});

Verify submission success

Check for confirmation messages, URL changes, or response status after submitting a form.
await page.click('button[type="submit"]');

// Check for a success message or URL change
await page.waitForSelector("text=Your response has been recorded.");
const currentUrl = page.url();
console.log(`Submission complete. Redirected to: ${currentUrl}`);

Next steps

Session live view

Learn how to watch test sessions in real time

Uploads

Learn how to upload files with Browserbase

Browserbase Functions

Deploy form automation as serverless functions