Skip to main content
See which browsers Extension.js supports and validate your extension across Chrome, Edge, Firefox, and custom binaries from a single CLI workflow within the same project.

Choose the right target

How it works

Use --browser to choose a target in dev, start, preview, and build. If you do not specify a browser, the CLI defaults to chromium. safari (and its webkit-based alias) is the exception: itโ€™s an alpha, macOS-only build target supported by build and dev only โ€” not preview or start. See Building Safari extensions.

Requested target vs. launch binary

The browser you request determines the artifact. The binary is just the runtime. When you run extension dev --browser=chromium, Extension.js always:
  • Writes output to dist/chromium (the folder is named after the requested target, never after the binary that launches).
  • Resolves browser-specific manifest fields for the requested target.
If the requested browser is not installed, Extension.js does not change the target. For chrome and chromium it looks for another managed Chromium-family binary (one previously downloaded by npx extension install) and uses it as the runtime instead:
  • Requested chromium missing: falls back to managed Chrome, then managed Edge.
  • Requested chrome missing: falls back to managed Chromium, then managed Edge.
When this happens, the CLI prints an info line naming the substitute binary and its path, and suggests npx extension install <browser> to get the browser you asked for. The output folder and the emitted manifest are exactly what they would be without the fallback. Within the Chromium family this substitution is safe: dist/chrome and dist/chromium are byte-identical because manifest prefixes resolve per engine family, not per vendor. See Browser-specific manifest fields for the prefix rules. To pre-install managed binaries for reproducible runs, use npx extension install <browser> or npx extension install all (which covers chromium too).

Supported browsers

Named browser targets: Named forks (auto-located from your system, no binary path required): If a named fork is not installed, Extension.js exits with install guidance. See Running other browsers. Engine-based targets (custom binary required): Extension.js treats firefox-based as a Gecko engine target internally.

Safari and other WebKit targets

In addition to the Chromium family and Firefox (Gecko engine), Extension.js can build your extension into a Safari app on macOS. Safari is a build target: build and dev are supported, but preview and start are not (Safari extensions canโ€™t be auto-loaded into a live browser). It requires macOS with the full Xcode app. See Building Safari extensions for the full workflow, requirements, and how to enable the extension in Safari.

Multi-browser selection

You can run multiple named browsers in one command:
Use comma-separated values to run multiple named targets in sequence (for example, --browser=chrome,edge,firefox).

Constraints and behavior

  • chromium-based requires --chromium-binary in commands that launch a browser (dev, start, preview); build needs no binary.
  • gecko-based / firefox-based require --gecko-binary under the same conditions.
  • Engine-based targets route to the same Chromium/Firefox runners with engine-aware behavior.
  • As build targets, engine targets get their own dist/<target> folder, .env.<target> resolution, EXTENSION_BROWSER value, and manifest prefix โ€” see What engine targets mean for build.

Best practices

  • Use named browsers for daily iteration: chrome, edge, and firefox are the fastest path for regular testing.
  • Use engine-based mode intentionally: Prefer chromium-based / gecko-based when validating custom binaries or shipping a family-generic build.
  • Keep profiles isolated per browser: Reduce cross-browser state leakage while debugging.
  • Pair with browser-specific fields: Use browser-prefixed manifest keys for true behavior differences.

Next steps