Skip to main content

Lib/webbrowser.py

cpython 3.14 @ ab2d84fe1023/Lib/webbrowser.py

webbrowser provides a high-level interface for opening URLs in the user's preferred web browser. It maintains a registry of named browser controllers, selects one automatically based on the platform and the BROWSER environment variable, and exposes three top-level functions (open, open_new, open_new_tab) that delegate to whichever controller is active. The module is pure Python with no C extension dependency, which makes it straightforward to read in full.

Map

LinesSymbolRolegopy
1–30module header, importssubprocess, os, shlex, shutil imports; __all__ declaration
31–70Error, open, open_new, open_new_tabPublic API entry points; lazy-initialize _tryorder and _browsers
71–120get, register, register_standard_browsersRegistry management; _tryorder list and _browsers dict
121–175BaseBrowserAbstract base: name, open, open_new, open_new_tab
176–220GenericBrowserRuns a browser command via subprocess; handles %s substitution
221–260BackgroundBrowserSubclass of GenericBrowser; adds & / detached launch on POSIX
261–310MozillaMozilla family: tries --new-tab and --new-window flags
311–350Galeon, Grail, OperaLegacy POSIX browser subclasses; kept for compatibility
351–400KonquerorKDE browser; uses kfmclient as the open command
401–440MacOSX, MacOSXOSAScriptmacOS controllers; MacOSXOSAScript drives AppleScript via osascript
441–490WindowsDefaultWindows controller; delegates to os.startfile or ShellExecute
491–540EdgeMicrosoft Edge subclass; passes --new-tab on new-tab requests
541–580Platform registration blockCalls register_standard_browsers; populates _tryorder at import time
581–600__main__ blockMinimal CLI: python -m webbrowser <url>

Reading

Registry bootstrap (lines 71 to 120)

cpython 3.14 @ ab2d84fe1023/Lib/webbrowser.py#L71-120

The registry is two module-level variables: _browsers maps a lower-cased name to either a callable or an already-constructed controller instance, and _tryorder is an ordered list of names used when no explicit browser is requested.

def register(name, klass, instance=None, *, preferred=False):
"""Register a browser connector."""
if klass is None and instance is None:
raise ValueError("at least one of klass or instance must be provided")
if instance is None:
instance = klass()
if preferred or name not in _tryorder:
_tryorder.insert(0, name) if preferred else _tryorder.append(name)
_browsers[name.lower()] = instance

get(using=None) walks _tryorder and returns the first controller whose binary can be found on PATH. If the BROWSER environment variable is set, its colon-separated entries are tried first, so user preference always wins over the platform defaults that register_standard_browsers adds.

GenericBrowser.open (lines 176 to 220)

cpython 3.14 @ ab2d84fe1023/Lib/webbrowser.py#L176-220

GenericBrowser is the workhorse for plain command-line browsers. Its open method builds an argument list by substituting %s with the URL, then calls subprocess.call (blocking) or subprocess.Popen (non-blocking depending on the subclass flag).

def open(self, url, new=0, autoraise=True):
sys.audit("webbrowser.open", url)
cmdline = [self.name] + [arg.replace("%s", url)
for arg in self.args]
try:
if sys.platform[:3] == 'win':
p = subprocess.Popen(cmdline)
else:
p = subprocess.Popen(cmdline, close_fds=True)
return not p.wait()
except OSError:
return False

The sys.audit call at the top is the security hook added in Python 3.8. Any registered audit hook can veto the call by raising an exception.

MacOSXOSAScript (lines 401 to 440)

cpython 3.14 @ ab2d84fe1023/Lib/webbrowser.py#L401-440

On macOS the preferred controller drives the browser through AppleScript so that the OS handles focus, profile selection, and the active-window heuristic. The implementation shells out to osascript -e.

class MacOSXOSAScript(BaseBrowser):
def open(self, url, new=0, autoraise=True):
if self._name == 'default':
script = f'open location "{url}"'
else:
script = f'''
tell application "{self._name}"
activate
open location "{url}"
end tell
'''
osapipe = os.popen("osascript", "w")
if osapipe is None:
return False
osapipe.write(script)
rc = osapipe.close()
return not rc

The new parameter is ignored here because AppleScript's open location always lets the browser decide whether to reuse an existing window.

gopy mirror

webbrowser has not been ported to gopy. The module is pure Python and has no numeric-heavy logic, so the most pragmatic path when it is needed is to ship the CPython source verbatim under stdlib/webbrowser.py and let the gopy interpreter execute it. The OS-specific controller classes (MacOSXOSAScript, WindowsDefault) rely on platform APIs that are not yet exposed in gopy's os and subprocess stubs, so those paths will fall back to GenericBrowser until the stubs are filled in.

CPython 3.14 changes

CPython 3.14 did not introduce breaking changes to webbrowser. The main movement in recent cycles was the addition of Edge as a registered browser on Windows (3.12) and the sys.audit hook on open (3.8). The Grail browser class, which was already dead code, remains present for historical compatibility. The register_standard_browsers refactor that landed in 3.13 extracted the platform-detection block into its own function, making the module-level code cleaner to read.