Start Firefox with Selenium, then install the extension with driver.install_addon(). For a published add-on, pass the absolute path to its signed .xpi file. For an unsigned extension you are developing, pass its directory or ZIP and set temporary=True.
Install a Firefox extension in a local Selenium session
Use Selenium’s current Firefox driver API rather than adding the extension to a profile before the browser starts. The extension artifact must be accessible at the path you pass. Selenium’s Firefox guide describes installing add-ons after creating the driver.
- Install or upgrade Selenium in the Python environment:
python -m pip install -U selenium. The current Selenium Python client documentation lists Python 3.10 or later. Selenium Python documentation - Get the extension file. For a published extension, use its signed
.xpipackage, such as one obtained from Mozilla Add-ons. - Resolve the artifact path to an absolute path, create Firefox, and call
install_addon(). - Keep the returned add-on identifier if you may want to uninstall the extension during the session.
from pathlib import Path
from selenium import webdriver
extension_path = Path("extensions/my_extension.xpi").resolve()
driver = webdriver.Firefox()
addon_id = driver.install_addon(str(extension_path))
try:
driver.get("https://example.com")
# Run browser automation with the extension installed.
finally:
driver.quit()
The finally block ensures the browser is shut down if navigation or later automation raises an exception. Firefox starts before the add-on installation call; the installed add-on is available to the session that follows.
Choose the right artifact and installation mode
| Extension case | What to pass | How to install | Expected lifetime |
|---|---|---|---|
| Published, signed add-on | Absolute path to its signed .xpi |
driver.install_addon(path) |
Installed in the Firefox session; use the returned identifier to uninstall it if needed. |
| Unfinished or unpublished unsigned add-on | Absolute path to the unpacked extension directory or a ZIP package | driver.install_addon(path, temporary=True) |
Temporary installation for the session; Selenium’s Firefox guide says unsigned unfinished extensions can only be installed temporarily. |
Selenium’s Firefox documentation identifies a signed XPI as the normal route for published add-ons and notes that unfinished or unpublished extensions are likely unsigned. The Python API documents the path argument as absolute and exposes the temporary flag. Firefox WebDriver API
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
Load an unsigned development extension
For a local unpacked extension directory or ZIP, enable temporary installation explicitly:
from pathlib import Path
from selenium import webdriver
extension_path = Path("build/my_extension").resolve()
driver = webdriver.Firefox()
try:
addon_id = driver.install_addon(str(extension_path), temporary=True)
driver.get("https://example.com")
# Test the extension while this Firefox session is running.
finally:
driver.quit()
Do not use temporary=True as a way to turn an unsigned development build into a persistent published add-on. It is for temporary loading during a session.
Uninstall an add-on before closing Firefox
install_addon() returns an identifier that can be passed to uninstall_addon(). This is useful when a test needs to remove the extension and continue using the same browser session.
from pathlib import Path
from selenium import webdriver
extension_path = Path("extensions/my_extension.xpi").resolve()
driver = webdriver.Firefox()
try:
addon_id = driver.install_addon(str(extension_path))
driver.get("https://example.com")
# Run checks that require the extension.
driver.uninstall_addon(addon_id)
finally:
driver.quit()
The method signatures and return value are documented in the Selenium Firefox WebDriver API.
Free tools Windows power users keep installed
One-click scans. No signup required.
Firefox, driver, and profile considerations
- Firefox compatibility: Selenium’s Firefox guide specifies Firefox 78 or later for Selenium 4 and recommends using the latest GeckoDriver. This is a documented minimum, not a guarantee that every extension works with every Firefox release. Firefox guide
- Browser and driver setup: Selenium Manager handles browser and driver setup for most supported platforms when a WebDriver starts. You can still install and specify them explicitly when your environment requires it. Selenium WebDriver documentation
- Existing profiles: The documented Python
FirefoxProfileconstructor clones a profile passed to it. The current Firefox installation method is still to start the driver and callinstall_addon(); avoid relying on olderFirefoxProfile.add_extension()examples as the current procedure. Firefox profile API
Remote WebDriver and Grid
With a remote session, the browser runs on a remote node. Make sure the extension artifact is available through that Grid deployment; a path on the Python client machine is not necessarily a path the browser node can read. The exact file-transfer approach depends on the remote WebDriver or Grid configuration, so verify it against the documentation for the environment you use. Selenium’s Firefox guide directs remote users to its Remote WebDriver guidance but does not establish one universal transfer command for every Grid setup. Firefox guide
Troubleshooting
- “Path must be absolute” or file not found: Resolve the path before installing, for example with
Path("extensions/my_extension.xpi").resolve(). Confirm that the resulting file or directory exists where Firefox can access it. - An unsigned extension will not install normally: For an unfinished or unpublished extension, use its directory or ZIP with
temporary=True. For a published add-on, use its signed XPI. - The add-on is missing in a remote session: Check whether the artifact is accessible to the remote browser node. Do not assume the local client path is shared with Grid.
- Firefox or GeckoDriver fails to start: Confirm that the environment meets Selenium’s Firefox version guidance and that browser/driver setup is available. Selenium Manager handles setup in most supported cases; custom or restricted environments may need explicit installation and configuration.
- The add-on installs but its behavior is wrong: Installation success does not establish compatibility with the Firefox release or with the extension’s own permissions and configuration. Check the extension’s requirements and test in the same browser environment used by the automation.
Or skip the browser setup:
If you need website screenshots rather than an extension-enabled Firefox automation session, ScreenshotNeo provides a website screenshot API. Its one-call endpoint returns an image or PDF; it is not a replacement for running Selenium or testing an extension inside Firefox. The API removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed; and its MCP server lets AI agents take screenshots.
cURL example, with the target URL adapted to your page:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for request options. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.
Frequently Asked Questions
Can I install a Firefox extension before calling webdriver.Firefox()?
The current Selenium Firefox workflow is to create the WebDriver first and then call `driver.install_addon()`.
Does install_addon() return an extension ID?
Yes. It returns an identifier that you can pass to `driver.uninstall_addon()`.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




