Firefox supports browser automation via multiple tools — useful for testing, scraping, accessibility checks, and CI workflows. Here's a practical guide to each option.
Playwright (Recommended)
Playwright is the most actively developed cross-browser automation framework. It supports Chromium, Firefox (via Playwright's bundled Gecko), and WebKit.
npm install playwright
npx playwright install firefox
Basic example:
const { firefox } = require('playwright');
(async () => {
const browser = await firefox.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
console.log(title);
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
})();
Playwright advantages over older tools:
- Built-in auto-wait (waits for elements to be ready before interacting)
- Network interception API (intercept/mock HTTP requests)
- Multiple contexts (test isolated browser sessions)
- Trace viewer for debugging recorded runs
- Good Firefox support
WebDriver / Selenium
Older standard. Firefox uses GeckoDriver as the WebDriver implementation.
npm install selenium-webdriver geckodriver
const { Builder, By } = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const driver = new Builder()
.forBrowser('firefox')
.setFirefoxOptions(new firefox.Options().headless())
.build();
When to use Selenium: If you have existing Selenium tests you're maintaining, or if you need the WebDriver standard for compliance/cross-tool compatibility.
Firefox CDP (Chrome DevTools Protocol)
Firefox supports a subset of CDP (needed for compatibility with Chrome-targeted tools). This enables Playwright's Firefox support under the hood.
If you have existing Chrome automation using CDP, Firefox's CDP support may let you run it on Firefox with minimal changes.
Puppeteer with Firefox
Puppeteer recently added Firefox support (Puppeteer 22+, 2024):
npm install puppeteer
npx puppeteer browsers install firefox
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({
browser: 'firefox',
headless: true
});
Note: Puppeteer's Firefox support is newer and less battle-tested than Playwright's. Playwright is generally more reliable for Firefox automation.
Firefox Headless Mode (Direct CLI)
Firefox ships with native headless mode (no display required):
firefox --headless --screenshot output.png https://example.com
firefox --headless --window-size=1280,720 --screenshot output.png https://example.com
For simple one-off screenshots, the CLI works without any npm dependencies.
Print to PDF:
firefox --headless --print-to-pdf output.pdf https://example.com
Testing Extensions
To test a Firefox extension automatically with Playwright:
const { firefox } = require('playwright');
const path = require('path');
const extensionPath = path.resolve('./extension');
const context = await firefox.launchPersistentContext('', {
headless: false, // Headless + extensions has limitations in some versions
args: ['-wait-for-browser', '--load-extension=' + extensionPath]
});
Note: Loading unpacked extensions in headless Firefox has limitations — behavior can differ from headed mode. Some extension testing requires headed mode.
CI/CD Integration
For running Firefox automation in CI (GitHub Actions, GitLab CI, etc.):
GitHub Actions:
- name: Install Firefox
uses: browser-actions/setup-firefox@latest
with:
firefox-version: latest
- name: Run tests
run: npx playwright test
env:
DISPLAY: ':99' # Required if running headed tests on Linux
Playwright's --headed mode in CI requires either a virtual display (Xvfb) or use of their built-in --headed Docker images.
Headless is simpler: For CI, use headless: true — no display server needed.
Firefox with Testing Profiles
Playwright and Selenium support using a custom Firefox profile, useful for pre-configured state (logged-in sessions, specific preferences):
// Playwright: use persistent context to maintain profile state
const context = await firefox.launchPersistentContext('./my-firefox-profile', {
headless: true
});
Useful Automation Patterns
Capturing CSRF tokens:
let csrfToken;
page.on('response', async res => {
const text = await res.text().catch(() => '');
const match = text.match(/name="csrf-token" content="([^"]+)"/);
if (match) csrfToken = match[1];
});
Network throttling:
// Playwright doesn't have built-in Firefox throttling,
// but you can use CDP:
const client = await page.context().newCDPSession(page);
await client.send('Network.emulateNetworkConditions', {
downloadThroughput: 1.6e6 / 8, // 1.6 Mbps
uploadThroughput: 750 * 1024 / 8,
latency: 150
});
For new projects: Playwright is the best starting point for Firefox automation. It's actively maintained, has excellent Firefox support, and the auto-wait feature alone prevents most flaky test issues.
Top comments (0)