Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If Selenium stops at “Launching Firefox…”, first capture geckodriver trace logs, then verify the exact Firefox and geckodriver executables and confirm that both processes can access Selenium’s temporary profile directory. On Ubuntu Snap or Flatpak installations, the most common cause is a sandboxed filesystem that hides the generated profile from Firefox or geckodriver. A clean native Firefox installation, a clean temporary profile, and matching browser-driver confinement provide the fastest baseline.

What the “Launching Firefox…” stall means

Selenium has requested a new Firefox session, but the startup exchange has not completed. The message does not identify one specific defect: the browser may be the wrong executable, geckodriver may be undiscoverable or incompatible, Firefox may be unable to read the generated profile, or a package sandbox may place the two processes in different filesystem views.

Geckodriver is a separate WebDriver server. Selenium normally finds it through PATH, unless you configure a specific executable. Selenium’s Firefox documentation states that Selenium 4 requires Firefox 78 or newer and recommends the latest geckodriver. The exact frequency of this stall has not been established by a trustworthy published benchmark, so treat each incident as an environment-specific diagnostic problem.

1. Capture trace evidence before changing settings

Do not begin by adding random delays, disabling security features, or repeatedly reinstalling packages. Mozilla’s Firefox Source Docs says trace-level output is vital because it records WebDriver requests, protocol traffic, and Marionette messages.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Run geckodriver directly

geckodriver -vv

Start the command in a terminal, then run your Selenium test in another terminal. Preserve all output, especially the final lines before the hang.

Write logs from Selenium

In Python, configure a Firefox service with trace logging and a file destination:

from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options

options = Options()
service = Service(log_output="geckodriver.log", service_args=["--log", "trace"])
driver = webdriver.Firefox(service=service, options=options)
try:
    driver.get("https://example.com")
finally:
    driver.quit()

If your Selenium binding exposes a different service-argument API, use the equivalent --log trace setting. In CI, always redirect the driver output to a retained artifact so a failed job does not erase the startup exchange.

Interpret the last successful step

  • A failure while locating or validating Firefox points to the binary path or package launcher.
  • Messages about creating, copying, or opening a profile point to permissions, TMPDIR, --profile-root, or sandbox visibility.
  • A driver protocol or Marionette mismatch points to browser, geckodriver, or Selenium compatibility.
  • A successful local launch followed by a CI-only hang points to display, user, container, or filesystem differences; test headless mode after the baseline works.

2. Verify which Firefox executable Selenium is using

Selenium supports selecting an alternate Firefox binary. Make the path explicit while diagnosing so a wrapper, launcher, or stale installation cannot be mistaken for the real executable.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Find the candidate paths

which firefox
which geckodriver
readlink -f "$(which firefox)"
readlink -f "$(which geckodriver)"

On Windows, use the full path to firefox.exe and geckodriver.exe; on macOS, identify the executable inside the Firefox application bundle. The important result is the actual executable, not merely a shell alias.

Set the Firefox binary explicitly in Python

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service

options = Options()
options.binary_location = "/path/to/firefox"
service = Service(executable_path="/path/to/geckodriver",
                  log_output="geckodriver.log",
                  service_args=["--log", "trace"])
driver = webdriver.Firefox(service=service, options=options)
try:
    driver.get("https://example.com")
finally:
    driver.quit()

Replace both paths with files that exist and are executable by the account running the test.

Special case: Ubuntu Snap

Mozilla warns that supplying /snap/bin/firefox as the binary can produce “binary is not a Firefox executable.” The Snap path is a launcher, not necessarily the confined Firefox binary geckodriver expects. If you keep Ubuntu’s Snap Firefox, use the matching confined geckodriver at /snap/bin/geckodriver and follow the package’s documented binary arrangement. Otherwise install a non-container Firefox release together with its matching geckodriver and configure both explicitly.

3. Check geckodriver discovery and version compatibility

Confirm that the driver Selenium starts is the one you intended:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
geckodriver --version
firefox --version

Check the trace log for the resolved driver path. Remove old copies earlier on PATH, or pass Service(executable_path=...) so there is no ambiguity. Keep Selenium, Firefox, and geckodriver current enough to support one another. Selenium’s current guidance recommends the latest geckodriver; its Firefox documentation requires Selenium 3.11 or newer for geckodriver and states that Selenium 4 requires Firefox 78 or newer.

Do not assume that upgrading only Selenium repairs a package mismatch. A newly installed driver can still start the wrong Firefox wrapper, and a current Firefox can still be invisible to a driver running in another confinement.

4. Treat Snap and Flatpak as filesystem problems

Containerized Firefox may see a different filesystem from geckodriver. Selenium generates a temporary profile, and Firefox can hang at startup if that profile is outside the sandbox’s accessible paths. This is a visibility problem, not a page-loading problem.

Use matching confinement

For Ubuntu Snap Firefox, use /snap/bin/geckodriver so the driver runs in the same confinement. A native Firefox installation paired with a native geckodriver is the simplest baseline. Do not mix a host geckodriver with a confined browser unless the package documentation explicitly supports that arrangement.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose an accessible profile root

If the sandboxed package must remain, set TMPDIR or geckodriver’s --profile-root to a directory both processes can read and write:

mkdir -p "$HOME/selenium-tmp"
chmod 700 "$HOME/selenium-tmp"
TMPDIR="$HOME/selenium-tmp" python your_test.py

Use a directory inside the package’s permitted filesystem. The exact allowed locations depend on the Snap or Flatpak policy; consult that package’s confinement documentation rather than copying a path from another distribution.

Check permissions as the test user

id
ls -ld "$TMPDIR" /tmp
 touch "$HOME/selenium-tmp/write-test"

The user launching CI must be able to create, read, rename, and delete files there. A directory writable only by your interactive account can still fail under a service user.

5. Reduce profile variables

Begin with Selenium’s anonymous temporary profile. If you pass a custom profile, Selenium copies it into a new temporary directory; a large profile, lock file, extension, or inaccessible preference can hide the underlying failure.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Baseline with no custom profile

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

options = Options()
driver = webdriver.Firefox(options=options)
try:
    driver.get("https://example.com")
finally:
    driver.quit()

If this works, add your custom profile, preferences, and extensions one at a time. Never point two simultaneous Firefox processes at the same live profile.

Use a dedicated profile only when necessary

Keep the source profile small and readable, and let Selenium copy it. Remove stale lock files from disposable test profiles. For CI, create a fresh workspace per job instead of reusing a developer’s home-directory profile.

6. Add headless mode after a normal launch works

Firefox accepts the -headless argument. Headless mode removes display-server requirements common in CI, but it cannot repair an invalid binary path, an inaccessible profile, or a driver mismatch.

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

options = Options()
options.add_argument("-headless")
driver = webdriver.Firefox(options=options)
try:
    driver.get("https://example.com")
finally:
    driver.quit()

When possible, prove a normal local launch first, then enable headless mode in the same environment. If only headless mode fails, compare the CI user, DISPLAY variables, container mounts, resource limits, and temporary-directory permissions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Remedy comparison

Environment Best baseline Profile requirement Driver path Logging
Native Firefox Clean temporary profile Any directory writable by the test user PATH or explicit native executable Retain trace output
Ubuntu Snap Firefox Matching Snap geckodriver Path visible inside the Snap confinement /snap/bin/geckodriver and a supported Firefox binary arrangement Retain trace output
Flatpak Firefox Matching sandbox-aware setup Use an allowed profile root via --profile-root or TMPDIR Driver must see the same browser and filesystem Retain trace output
CI or Docker Fresh workspace and clean profile Shared writable mount for both processes Explicit paths preferred Save logs as build artifacts

Troubleshooting common symptoms

“binary is not a Firefox executable”

Cause: Selenium was given a launcher such as /snap/bin/firefox rather than a supported executable path. Fix: remove the override, use the package’s documented full binary with matching confined geckodriver, or install native Firefox and point Selenium to it.

Geckodriver starts but Firefox never appears

Cause: profile creation or access failed. Fix: inspect trace lines around profile creation, test a clean profile, verify the effective TMPDIR, and ensure the CI user can write there.

Works locally, hangs in Docker or CI

Cause: different user, mount, package confinement, display configuration, or resource limits. Fix: print executable paths and versions in the job, retain trace logs, use a fresh writable profile root, then add -headless.

Only a custom profile fails

Cause: locked files, extensions, oversized data, or inaccessible copied contents. Fix: return to the anonymous profile and reintroduce profile changes individually.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Repeated retries change nothing

Cause: retries preserve the same invalid path or inaccessible directory. Fix: stop retrying, capture one complete trace, and correct the environment identified by the final successful startup step.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a rendered screenshot rather than WebDriver control, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; those steps can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers.

One GET request returns PNG, JPEG, WebP, or PDF:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the complete option list and response details in the ScreenshotNeo documentation. Options include full-page lazy-image loading, CSS-element capture, dark mode, 12 device presets or custom viewports, retina scale, PDF paper settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of 100 URLs per call, usage data, and an OpenAPI specification. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

The Free plan includes 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 screenshots; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

FAQ

Should I delete every Firefox profile?

No. Use a disposable clean profile for diagnosis and delete only profiles you created for testing. Do not remove a personal profile before confirming its contents are backed up.

Can increasing Selenium’s timeout fix this stall?

A longer timeout can provide more time for a slow machine, but it does not fix an inaccessible profile, wrong executable, or incompatible driver. Trace the startup exchange first.

Is headless Firefox required in Docker?

No. It is often useful where no display server exists, but a normal launch is the better diagnostic baseline when available.

Frequently Asked Questions

Should I delete every Firefox profile?

No. Use a disposable clean profile for diagnosis and delete only profiles created for testing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can increasing Selenium’s timeout fix this stall?

A longer timeout may help a slow machine, but it cannot fix an inaccessible profile, wrong executable, or incompatible driver.

Is headless Firefox required in Docker?

No. It is useful without a display server, but first establish a working baseline with correct paths and profile access.

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.