Browser Provider
The Browser Provider enables automated web browser interactions for testing complex web applications and JavaScript-heavy websites where simpler providers are not sufficient.
This provider uses Playwright to control headless browsers, allowing you to navigate pages, interact with elements, and extract data from dynamic websites. Playwright supports Chromium (Chrome, Edge), Firefox, and WebKit (Safari engine) browsers.
When to Use the Browser Provider
The Browser Provider should only be used when simpler alternatives are not possible:
-
Try these first:
- HTTP Provider - For API calls and simple HTML responses
- WebSocket Provider - For real-time connections
- Custom Python Provider - For custom logic with existing libraries
- Custom JavaScript Provider - For Node.js-based solutions
-
Use Browser Provider only when:
- The application requires JavaScript execution to render content
- You need to interact with complex UI elements (dropdowns, modals, etc.)
- Authentication requires browser-based workflows (OAuth, SSO)
- You need to test actual user interactions (clicks, typing, scrolling)
Important Considerations
When using browser automation:
- Rate Limiting: Always implement delays between requests to avoid overwhelming servers
- Anti-Bot Detection: Many websites employ anti-bot measures that can detect and block automated browsers
- Resource Usage: Browser automation is 10-100x slower than direct API calls and consumes significant CPU/memory
- Legal Compliance: Always check the website's Terms of Service and robots.txt before automating
Prerequisites
Playwright is a peer dependency of promptfoo, so you will need to install it separately:
npm install playwright @playwright/browser-chromium playwright-extra puppeteer-extra-plugin-stealth
Note: Currently, promptfoo's browser provider only supports Chromium-based browsers (Chrome, Edge). The provider uses playwright-extra
with the Chromium engine for enhanced stealth capabilities.
Configuration
To use the Browser Provider, set the provider id
to browser
and define a series of steps
to execute:
providers:
- id: browser
config:
steps:
- action: navigate
args:
url: 'https://example.com'
- action: type
args:
selector: '#search-input'
text: '{{prompt}}'
- action: click
args:
selector: '#search-button'
- action: extract
args:
selector: '#results'
name: searchResults
transformResponse: 'extracted.searchResults'
Connecting to Existing Browser Sessions
You can connect to an existing Chrome browser session (e.g., with OAuth authentication already completed):
providers:
- id: browser
config:
connectOptions:
debuggingPort: 9222 # Chrome debugging port
steps:
# Your test steps here
Setup Instructions:
- Start Chrome with debugging:
chrome --remote-debugging-port=9222 --user-data-dir=/tmp/test
- Complete authentication manually
- Run your tests
Connection Options:
debuggingPort
: Port number for Chrome DevTools Protocol (default: 9222)mode
: Connection mode -'cdp'
(default) or'websocket'
wsEndpoint
: Direct WebSocket endpoint (when usingmode: 'websocket'
)
Supported Actions
The Browser Provider supports the following actions:
Core Actions
1. navigate
- Load a webpage
Navigate to a specified URL.
- action: navigate
args:
url: 'https://example.com/search?q={{query}}'
2. click
- Click an element
Click on any clickable element (button, link, etc.).
- action: click
args:
selector: 'button[type="submit"]'
optional: true # Won't fail if element doesn't exist
3. type
- Enter text
Type text into input fields, textareas, or any editable element.
- action: type
args:
selector: 'input[name="username"]'
text: '{{username}}'
Special keys:
<enter>
- Press Enter key<tab>
- Press Tab key<escape>
- Press Escape key
4. extract
- Get text content
Extract text from any element. The extracted content is available in transformResponse
.
- action: extract
args:
selector: '.result-title'
name: title # Access as extracted.title
5. wait
- Pause execution
Wait for a specified duration (in milliseconds).
- action: wait
args:
ms: 3000 # Wait 3 seconds
6. waitForNewChildren
- Wait for dynamic content
Wait for new elements to appear under a parent element. Useful for content loaded via AJAX.
- action: waitForNewChildren
args:
parentSelector: '#results-container'
delay: 500 # Check every 500ms
timeout: 10000 # Max wait time 10 seconds
7. screenshot
- Capture the page
Take a screenshot of the current page state.
- action: screenshot
args:
path: 'screenshot.png'
fullPage: true # Capture entire page, not just viewport
Action Parameters
Action | Required Args | Optional Args | Description |
---|---|---|---|
navigate | url | - | URL to navigate to |
click | selector | optional | CSS selector of element to click |
type | selector , text | - | CSS selector and text to type |
extract | selector , name | - | CSS selector and variable name |
wait | ms | - | Milliseconds to wait |
waitForNewChildren | parentSelector | delay , timeout | Parent element to watch |
screenshot | path | fullPage | File path to save screenshot |
Response Parsing
Use the transformResponse
config option to extract specific data from the results. The parser receives an object with two properties:
extracted
: An object containing named results fromextract
actionsfinalHtml
: The final HTML content of the page after all actions are completed
Variables and Templating
You can use Nunjucks templating in your configuration, including the {{prompt}}
variable and any other variables passed in the test context.
providers:
- id: browser
config:
steps:
- action: navigate
args:
url: 'https://example.com/search?q={{prompt}}'
- action: extract
args:
selector: '#first-result'
name: topResult
transformResponse: 'extracted.topResult'
tests:
- vars:
prompt: 'What is the capital of France?'
Using as a Library
If you are using promptfoo as a node library, you can provide the equivalent provider config:
{
// ...
providers: [{
id: 'browser',
config: {
steps: [
{ action: 'navigate', args: { url: 'https://example.com' } },
{ action: 'type', args: { selector: '#search', text: '{{prompt}}' } },
{ action: 'click', args: { selector: '#submit' } },
{ action: 'extract', args: { selector: '#results' }, name: 'searchResults' }
],
transformResponse: (extracted, finalHtml) => extracted.searchResults,
}
}],
}
Reference
Supported config options:
Option | Type | Description |
---|---|---|
headless | boolean | Whether to run the browser in headless mode. Defaults to true . |
cookies | string | { name: string; value: string; domain?: string; path?: string; }[] | A string or array of cookies to set on the browser |
transformResponse | string | Function | A function or string representation of a function to parse the response. Receives an object with extracted and finalHtml parameters and should return a ProviderResponse |
steps | BrowserAction[] | An array of actions to perform in the browser |
timeoutMs | number | The maximum time in milliseconds to wait for the browser operations to complete |
Note: All string values in the config support Nunjucks templating. This means you can use the {{prompt}}
variable or any other variables passed in the test context.
Browser Support
While Playwright supports multiple browsers (Chromium, Firefox, and WebKit), promptfoo's browser provider currently only implements Chromium support. This includes:
- Chrome - Google's browser
- Edge - Microsoft's Chromium-based browser
- Chromium - Open-source browser project
The implementation uses playwright-extra
with the Chromium engine for enhanced stealth capabilities to avoid detection.
Supported Browser Actions
The steps
array in the configuration can include the following actions:
Action | Description | Required Args | Optional Args |
---|---|---|---|
navigate | Navigate to a specified URL | url : string | |
click | Click on an element | selector : string | optional : boolean |
extract | Extract text content from an element | selector : string, name : string | |
screenshot | Take a screenshot of the page | path : string | fullPage : boolean |
type | Type text into an input field | selector : string, text : string | |
wait | Wait for a specified amount of time | ms : number | |
waitForNewChildren | Wait for new child elements to appear under a parent | parentSelector : string | delay : number, timeout : number |
Each action in the steps
array should be an object with the following structure:
{
action: string;
args: {
[key: string]: any;
};
name?: string;
}
Each step in the steps
array should have the following structure:
action
: Specifies the type of action to perform (e.g., 'navigate', 'click', 'type').args
: Contains the required and optional arguments for the action.name
(optional): Used to name extracted content in the 'extract' action.
Steps are executed sequentially, enabling complex web interactions.
All string values in args
support Nunjucks templating, allowing use of variables like {{prompt}}
.
Advanced Features
Playwright Recorder Tools
The easiest way to create browser automation scripts is to record your interactions: