Skip to main content
Scrape a page to get clean data, then call /interact to start taking actions in that page - click buttons, fill forms, extract dynamic content, or navigate deeper. Just describe what you want, or write code if you need full control.

AI prompts

Describe what action you want to take in the page

Code execution

Interact via code execution securely with playwright, agent-browser

Live view

Watch or interact with the browser in real time via embeddable stream

How It Works

  1. Scrape a URL with POST /v2/scrape. The response includes a scrapeId in data.metadata.scrapeId. Optionally pass a profile to persist browser state across sessions.
  2. Interact by calling POST /v2/scrape/{scrapeId}/interact with a prompt or with playwright code. On the first call, the scraped session is resumed and you can start interacting with the page.
  3. Stop the session with DELETE /v2/scrape/{scrapeId}/interact when you’re done.

Quick Start

Scrape a page, interact with it, and stop the session:
from firecrawl import Firecrawl

app = Firecrawl(api_key="fc-YOUR-API-KEY")

# 1. Scrape Amazon's homepage
result = app.scrape("https://www.amazon.com", formats=["markdown"])
scrape_id = result.metadata["scrapeId"]

# 2. Interact — search for a product and get its price
app.interact(scrape_id, prompt="Search for iPhone 16 Pro Max")
response = app.interact(scrape_id, prompt="Click on the first result and tell me the price")
print(response.output)

# 3. Stop the session
app.stop_interaction(scrape_id)
Response
{
  "success": true,
  "liveViewUrl": "https://liveview.firecrawl.dev/...",
  "interactiveLiveViewUrl": "https://liveview.firecrawl.dev/...",
  "output": "The iPhone 16 Pro Max (256GB) is priced at $1,199.00.",
  "exitCode": 0,
  "killed": false
}

Interact via prompting

The simplest way to interact with a page. Describe what you want in natural language and it will click, type, scroll, and extract data automatically.
response = app.interact(scrape_id, prompt="What are the customer reviews saying about battery life?")
print(response.output)
The response includes an output field with the agent’s answer:
Response
{
  "success": true,
  "liveViewUrl": "https://liveview.firecrawl.dev/...",
  "interactiveLiveViewUrl": "https://liveview.firecrawl.dev/...",
  "output": "Customers are generally positive about battery life. Most reviewers report 8-10 hours of use on a single charge. A few noted it drains faster with heavy multitasking.",
  "stdout": "...",
  "result": "...",
  "stderr": "",
  "exitCode": 0,
  "killed": false
}

Keep Prompts Small and Focused

Prompts work best when each one is a single, clear task. Instead of asking the agent to do a complex multi-step workflow in one shot, break it into separate interact calls. Each call reuses the same browser session, so state carries over between them.

Running Code

For full control, you can execute code directly in the browser sandbox. The page variable (a Playwright Page object) is available in Node.js and Python. Bash mode has agent-browser pre-installed.

Node.js (Playwright)

The default language. Write Playwright code directly — page is already connected to the browser.
response = app.interact(scrape_id, code="""
// Click a button and wait for navigation
await page.click('#next-page');
await page.waitForLoadState('networkidle');

// Extract content from the new page
const title = await page.title();
const content = await page.$eval('.article-body', el => el.textContent);
JSON.stringify({ title, content });
""")
print(response.result)

Python

Set language to "python" for Playwright’s Python API.
response = app.interact(
    scrape_id,
    code="""
import json

await page.click('#load-more')
await page.wait_for_load_state('networkidle')

items = await page.query_selector_all('.item')
data = []
for item in items:
    text = await item.text_content()
    data.append(text.strip())

print(json.dumps(data))
""",
    language="python",
)
print(response.stdout)

Bash (agent-browser)

agent-browser is a CLI pre-installed in the sandbox with 60+ commands. It provides an accessibility tree with element refs (@e1, @e2, …) — ideal for LLM-driven automation.
# Take a snapshot to see interactive elements
snapshot = app.interact(
    scrape_id,
    code="agent-browser snapshot -i",
    language="bash",
)
print(snapshot.stdout)
# Output:
# [document]
#   @e1 [input type="text"] "Search..."
#   @e2 [button] "Search"
#   @e3 [link] "About"

# Interact with elements using @refs
app.interact(
    scrape_id,
    code='agent-browser fill @e1 "firecrawl" && agent-browser click @e2',
    language="bash",
)
Common agent-browser commands:
CommandDescription
snapshotFull accessibility tree with element refs
snapshot -iInteractive elements only
click @e1Click element by ref
fill @e1 "text"Clear field and type text
type @e1 "text"Type without clearing
press EnterPress a keyboard key
scroll down 500Scroll down by pixels
get text @e1Get text content
get urlGet current URL
wait @e1Wait for element
wait --load networkidleWait for network idle
find text "X" clickFind element by text and click
eval "js code"Run JavaScript in page

Live View

Every interact response includes URLs for watching the browser session in real time.
FieldDescription
liveViewUrlRead-only stream — embed to watch the session
interactiveLiveViewUrlInteractive stream — viewers can click, type, and interact
<!-- Read-only view -->
<iframe src="LIVE_VIEW_URL" width="100%" height="600" />

<!-- Interactive view — viewers can control the browser -->
<iframe src="INTERACTIVE_LIVE_VIEW_URL" width="100%" height="600" />
The interactive live view is useful for building user-facing UIs where end users need to see and interact with the browser — such as login flows, CAPTCHA solving, or guided workflows.

Session Lifecycle

Creation

The first POST /v2/scrape/{scrapeId}/interact call creates a sandboxed browser session at the same page state as your scrape.

Reuse

Subsequent interact calls on the same scrapeId reuse the existing session. The browser stays open and maintains its state between calls, so you can chain multiple interactions:
# First call — click a tab
app.interact(scrape_id, code="await page.click('#tab-2')")

# Second call — the tab is still selected, extract its content
result = app.interact(scrape_id, code="await page.$eval('#tab-2-content', el => el.textContent)")
print(result.result)

Cleanup

Stop the session explicitly when done:
app.stop_interaction(scrape_id)
Sessions also expire automatically based on TTL (default: 10 minutes) or inactivity timeout (default: 5 minutes).
Always stop sessions when you’re done to avoid unnecessary billing. Credits are prorated by the second.

Persistent Profiles

By default, each scrape + interact session starts with a clean browser. With profile, you can save and reuse browser state (cookies, localStorage, sessions) across scrapes. This is useful for staying logged in and preserving preferences. Pass the profile parameter when calling scrape. Sessions with the same profile name share state.
from firecrawl import Firecrawl

app = Firecrawl(api_key="fc-YOUR-API-KEY")

# Session 1: Scrape with a profile, log in, then stop (state is saved)
result = app.scrape(
    "https://app.example.com/login",
    formats=["markdown"],
    profile={"name": "my-app", "save_changes": True},
)
scrape_id = result.metadata["scrapeId"]

app.interact(scrape_id, prompt="Fill in user@example.com and password, then click Login")
app.stop_interaction(scrape_id)

# Session 2: Scrape with the same profile — already logged in
result = app.scrape(
    "https://app.example.com/dashboard",
    formats=["markdown"],
    profile={"name": "my-app", "save_changes": True},
)
scrape_id = result.metadata["scrapeId"]

response = app.interact(scrape_id, prompt="Extract the dashboard data")
print(response.output)
app.stop_interaction(scrape_id)
ParameterDefaultDescription
nameA name for the persistent profile. Scrapes with the same name share browser state.
saveChangestrueWhen true, browser state is saved back to the profile when the interact session stops. Set to false to load existing data without writing — useful when you need multiple concurrent readers.
Only one session can save to a profile at a time. If another session is already saving, you’ll get a 409 error. You can still open the same profile with saveChanges: false, or try again later.
The browser state is saved when the interact session is stopped. Always stop the session when you’re done so the profile can be reused.

When to Use What

Use CaseRecommendedWhy
Web searchSearchDedicated search endpoint
Get clean content from a URLScrapeOne API call, no session needed
Click, type, navigate on a pageInteract (prompt)Just describe it in English
Extract data behind interactionsInteract (prompt)No selectors needed
Complex scraping logicInteract (code)Full Playwright control
Interact vs Browser Sandbox: Interact is built on the same infrastructure as Browser Sandbox but provides a better interface for the most common pattern — scrape a page, then go deeper. Browser Sandbox is better when you need a standalone browser session that isn’t tied to a specific scrape.

Pricing

2 credits per session minute, prorated by the second. The scrape itself is billed separately (1 credit per scrape, plus any format-specific costs).

API Reference

Request Body (POST)

FieldTypeDefaultDescription
promptstringNatural language task for the AI agent. Required if code is not set. Max 10,000 characters.
codestringCode to execute (Node.js, Python, or Bash). Required if prompt is not set. Max 100,000 characters.
languagestring"node""node", "python", or "bash". Only used with code.
timeoutnumber30Timeout in seconds (1–300).
originstringCaller identifier for activity tracking.

Response

FieldDescription
successtrue if the execution completed without errors
liveViewUrlRead-only live view URL for the browser session
interactiveLiveViewUrlInteractive live view URL (viewers can control the browser)
outputThe agent’s natural language answer to your prompt. Only present when using prompt.
stdoutStandard output from the code execution
resultRaw return value from the sandbox. For code: the last expression evaluated. For prompt: the raw page snapshot the agent used to produce output.
stderrStandard error output
exitCodeExit code (0 = success)
killedtrue if the execution was terminated due to timeout

Have feedback or need help? Email help@firecrawl.com or reach out on Discord.