Guides
Practical walkthroughs for the most common web automation tasks.
Login Flow
Automate logging into any website. This pattern uses navigate, fill, click, and snapshot to complete a login form.
Steps
- Navigate to the login page
- Fill the email/username field
- Fill the password field
- Click the sign-in button (or submit the form)
- Snapshot to verify the result
# Login flow example
async def login(client, session_id, email, password):
# Navigate to login page
await client.post(
f"{BASE}/sessions/{session_id}/navigate",
headers=HEADERS,
json={"url": "https://app.example.com/login"},
)
# Fill email
await client.post(
f"{BASE}/sessions/{session_id}/fill",
headers=HEADERS,
json={"target": "Email address field", "value": email},
)
# Fill password
await client.post(
f"{BASE}/sessions/{session_id}/fill",
headers=HEADERS,
json={"target": "Password field", "value": password},
)
# Submit the login form
resp = await client.post(
f"{BASE}/sessions/{session_id}/submit",
headers=HEADERS,
json={"target": "the login form"},
)
snapshot = resp.json()["snapshot"]
# Check if login succeeded
if "dashboard" in snapshot["url"]:
print("Login successful!")
elif snapshot["alerts"]:
print(f"Login failed: {snapshot['alerts'][0]['text']}")
return snapshot
# 1. Navigate to login page
curl -X POST "https://api.babelwrap.com/v1/sessions/$SID/navigate" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://app.example.com/login"}'
# 2. Fill email
curl -X POST "https://api.babelwrap.com/v1/sessions/$SID/fill" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"target": "Email address field", "value": "user@example.com"}'
# 3. Fill password
curl -X POST "https://api.babelwrap.com/v1/sessions/$SID/fill" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"target": "Password field", "value": "secretpass123"}'
# 4. Submit the login form
curl -X POST "https://api.babelwrap.com/v1/sessions/$SID/submit" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"target": "the login form"}' | jq .snapshot.url
Form Submission
Fill and submit multi-field forms like contact forms, registration forms, or search filters.
Steps
- Navigate to the page with the form
- Fill each field in visual order (top to bottom)
- Submit the form
- Check the snapshot for success/error messages
# Fill a contact form with multiple fields
fields = [
("Name field", "Jane Doe"),
("Email field", "jane@example.com"),
("Subject field", "Partnership inquiry"),
("Message textarea", "Hi, I'd like to discuss a partnership..."),
]
for target, value in fields:
await client.post(
f"{BASE}/sessions/{session_id}/fill",
headers=HEADERS,
json={"target": target, "value": value},
)
# Handle a dropdown/select field
await client.post(
f"{BASE}/sessions/{session_id}/fill",
headers=HEADERS,
json={"target": "Department dropdown", "value": "Sales"},
)
# Submit
resp = await client.post(
f"{BASE}/sessions/{session_id}/submit",
headers=HEADERS,
json={}, # omit target for the default form
)
# Check for success
snapshot = resp.json()["snapshot"]
if snapshot["alerts"]:
for alert in snapshot["alerts"]:
print(f"{alert['type']}: {alert['text']}")
<select> dropdowns automatically. Just pass the visible option text as the value (e.g., "Sales" not the internal value).Data Extraction
Extract structured data from any page using natural language queries. BabelWrap uses an LLM to interpret the page content and return clean JSON.
Simple Extraction
# Navigate to a product listing page
await client.post(
f"{BASE}/sessions/{session_id}/navigate",
headers=HEADERS,
json={"url": "https://shop.example.com/products"},
)
# Extract product data
resp = await client.post(
f"{BASE}/sessions/{session_id}/extract",
headers=HEADERS,
json={"query": "all product names, prices, and availability"},
)
products = resp.json()["data"]
# [{"name": "Widget A", "price": "$29.99", "available": true}, ...]
Multi-Page Extraction
# Extract data across multiple pages
all_products = []
while True:
# Extract from current page
resp = await client.post(
f"{BASE}/sessions/{session_id}/extract",
headers=HEADERS,
json={"query": "all product names and prices on this page"},
)
all_products.extend(resp.json()["data"])
# Check if there's a next page
snapshot = resp.json()["snapshot"]
has_next = any(
a["label"].lower() in ("next", "next page", ">")
for a in snapshot["actions"]
)
if not has_next:
break
# Click next page
await client.post(
f"{BASE}/sessions/{session_id}/click",
headers=HEADERS,
json={"target": "Next page link"},
)
print(f"Extracted {len(all_products)} products across all pages")
Query Tips
- Be specific: "all product names and prices" is better than "everything on the page"
- Name the fields you want: "job title, company name, and location for each listing"
- For tables, describe the data: "all rows from the pricing table"
- For single values: "the total price shown" returns a scalar instead of an array
Multi-Step Checkout
Automate complex multi-page flows like e-commerce checkout. This combines all BabelWrap actions.
# Complete e-commerce checkout flow
async def checkout(client, session_id):
# 1. Navigate to product page
await client.post(
f"{BASE}/sessions/{session_id}/navigate",
headers=HEADERS,
json={"url": "https://shop.example.com/product/wireless-headphones"},
)
# 2. Add to cart
await client.post(
f"{BASE}/sessions/{session_id}/click",
headers=HEADERS,
json={"target": "Add to Cart button"},
)
# 3. Go to cart
await client.post(
f"{BASE}/sessions/{session_id}/click",
headers=HEADERS,
json={"target": "View Cart link"},
)
# 4. Proceed to checkout
await client.post(
f"{BASE}/sessions/{session_id}/click",
headers=HEADERS,
json={"target": "Proceed to Checkout button"},
)
# 5. Fill shipping info
shipping_fields = [
("First name", "Jane"),
("Last name", "Doe"),
("Address", "123 Main St"),
("City", "San Francisco"),
("State", "California"),
("ZIP code", "94102"),
]
for target, value in shipping_fields:
await client.post(
f"{BASE}/sessions/{session_id}/fill",
headers=HEADERS,
json={"target": target, "value": value},
)
# 6. Continue to payment
await client.post(
f"{BASE}/sessions/{session_id}/click",
headers=HEADERS,
json={"target": "Continue to Payment button"},
)
# 7. Extract order summary
resp = await client.post(
f"{BASE}/sessions/{session_id}/extract",
headers=HEADERS,
json={"query": "order total, items, and shipping cost"},
)
return resp.json()["data"]
Best Practices
- Always check snapshots -- verify the page state after each action before proceeding
- Be specific with targets -- "the blue Submit button" is better than "button"
- Clean up sessions -- always close sessions when done to free resources
- Handle errors gracefully -- check
alertsfor validation errors, watch forbot_detectedresponses - Use extract wisely -- ask for specific fields rather than "everything"
- Mind rate limits -- add small delays between actions for free tier; check
Retry-Afterheader on 429 responses
Going Further: Mapped Sites
Want to skip manual navigation entirely? If a site has been mapped, your agent can call typed tools like linkedin_search_jobs(query) instead of step-by-step browser actions. Mapped sites handle the full flow automatically, including authentication and self-healing when sites change.