Trying to get export_png to work in Bokeh 3.6.2 on Windows Conda

My goal is to export Bokeh plots as high-res publication-quality PNG files. I know this gets asked occasionally, but the latest postings I have found are a few years old and don’t seem to help in my situation. I am getting the following error when I try to export a figure as a PNG from Jupyter Lab running in Firefox from Conda in Windows.

RuntimeError: Neither firefox and geckodriver nor a variant of chromium browser and chromedriver are available on system PATH. You can install the former with ‘conda install -c conda-forge firefox geckodriver’.

As far as I can tell, I have installed all necessary packages that might be required, specifically firefox, geckodriver, selenium, and python-chromedriver-binary. Otherwise, this is a fresh Conda install. It seems like it shouldn’t require a lot effort to get export_png to function correctly, so I assume I’m missing something straightforward. I am new to Python, and I appreciate any advice people might be able to offer.

If Bokeh was a pure Python library that did all its work in Python, this would surely be the case. But in actuality, even though Bokeh is used from Python, very little work is done in Python. Instead, almost all the work (drawing, events, etc) is done in JavaScript, in a browser. This means, in particular, that in order to get PNG output, the Python Bokeh APIs needs to drive a headless browser to actually render things, and then save a screenshot (roughly speaking). But that means we have to rely on third-party tools like Selenium, Chromedriver, Geckodriver, etc. for controlling hedless browsers. And that means we are at the mercy of however easy and simple those tools are to install.

In principle, all that should be needed is to conda-install selenium and one of the webdrivers into the same conda env as the Bokeh package you are using. Bokeh will look in a few “standard” locations to try and find the necessary tools. It’s not really possible to say much more without more information. For instance, you might attach the output of conda list as well as verify that the bokeh you are importing is actually in the same environment as the webdrivers. Environment mismatches are a common headache I have observed (with Python in general). I have seen users accidentally run Jupyter from a different environment than they thought they were using, many times over the years.

Thank you for the reply, Bryan. I really appreciate your clear explanation of how Bokeh works. That makes sense. I also wasn’t meaning to criticize Bokeh. I see now that could have been taken in multiple ways. I just meant that whatever my problem is, it’s probably exaggerated by my inexperience. I am pasting below the output of conda list, as run from within the Jupyter Lab notebook I am trying to export plots from. I only pasted the packages mentioned above since the whole output exceeds the character limit of the reply. Based on this, I think everything is in the same environment. Does that seem correct? Is there anything else I can provide to shed light on the situation?

# packages in environment at C:\Users\user1\AppData\Local\anaconda3:
#
# Name                           Version              Build               Channel
bokeh                            3.6.2                py312haa95532_0
firefox                          112.0                h63175ca_0          conda-forge
geckodriver                      0.33.0               h611cf2b_0          conda-forge
python-chromedriver-binary       139.0.7223.0.0       pyha6a9232_0        conda-forge
selenium                         4.11.2               pyhd8ed1ab_0        conda-forge

@arete That looks like everything necessary is installed, so unfortunately I am not sure offhand what might be going wrong. What happens if you try to run geckodriver directly? For example when I run chromedriver from the terminal on my Mac, I see output like:

bk37 ❯ chromedriver
Starting ChromeDriver 135.0.7049.95 (de2eb485a1951079e63bdb57ce25544d2dc79c15-refs/branch-heads/7049@{#1836}) on port 0
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully on port 52280.

Perhaps if you run yourself, there will be some error message from the webdriver that points to an actual underlying issue.

Alternatively, you might try instead with Chrome and chromedriver to see if that works better.

You can also try running these Bokeh API functions, which should show lower level error messsages (e.g. on my laptop where firefox is not installed):

In [1]: from bokeh.io.webdriver import create_firefox_webdriver, create_chromium_webdriver

In [2]: create_firefox_webdriver()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[2], line 1
----> 1 create_firefox_webdriver()

File ~/anaconda3/envs/bk37/lib/python3.13/site-packages/bokeh/io/webdriver.py:65, in create_firefox_webdriver(scale_factor)
     63 firefox = which("firefox")
     64 if firefox is None:
---> 65     raise RuntimeError("firefox is not installed or not present on PATH")
     67 geckodriver = which("geckodriver")
     68 if geckodriver is None:

RuntimeError: firefox is not installed or not present on PATH

Looking at the Bokeh webdriver code, it actually seems like the current setup suppresses these messages which doesn’t seem helpful. It might be a good idea to open an issue to start passing on these errors to users so that more diagnostic information is available.

I finally got Bokeh working by using conda update --all. This got me up and running because it updated the version of Selenium from 4.11.2 to 4.24.0.

selenium           conda-forge/noarch::selenium-4.11.2-p~ --> pkgs/main/win-64::selenium-4.24.0-py312hefb1915_0

It is producing the desired PNG output, but it is still complaining about Geckodriver needing to be updated:

> The geckodriver version (0.33.0) detected in PATH at C:\Users\user1\AppData\Local\anaconda3\Scripts\geckodriver.exe might not be compatible with the detected firefox version (137.0.2.563); currently, geckodriver 0.36.0 is recommended for firefox 137.*, so it is advised to delete the driver in PATH and retry

The funny part is that Conda Forge says it will install version 0.36, but it actually installs version 0.33 when you execute conda install conda-forge::geckodriver. I can’t figure out why this mismatch exists, but as Bryan points out above, these things are out of control of the Bokeh team. I also agree that it would be good if the error reporting were a little more verbose. Hopefully this exchange helps others, and thank you again for your advice Bryan.