SeleniumHQ/selenium · error · ValueError
Download unavailable (HTTP {r.status}): {url}
Error message
Download unavailable (HTTP {r.status}): {url} What it means
Raised by calculate_hash() in scripts/pinned_browsers.py when the HTTP GET to a browser/driver download URL returns a non-200 status. The function streams the response body (preload_content=False) to compute sha256, so it checks status before reading. This is a CI/build script used to pin browser binaries for the Selenium Bazel build (common/repositories.bzl).
Source
Thrown at scripts/pinned_browsers.py:26
import urllib3
from packaging.version import parse
from scripts.generated_note import generated_note
# Find the current stable versions of each browser we
# support and the sha256 of these. That's useful for
# updating `//common:repositories.bzl`
http = urllib3.PoolManager()
def calculate_hash(url):
print(f"Calculate hash for {url}", file=sys.stderr)
h = hashlib.sha256()
r = http.request("GET", url, preload_content=False)
if r.status != 200:
raise ValueError(f"Download unavailable (HTTP {r.status}): {url}")
for b in iter(lambda: r.read(4096), b""):
h.update(b)
return h.hexdigest()
def get_chrome_info_for_channel(channel):
r = http.request(
"GET",
"https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json",
)
milestone = json.loads(r.data)["channels"][channel]["version"].split(".")[0]
r = http.request(
"GET",
"https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json",
)
versions = json.loads(r.data)["versions"]
return sorted(View on GitHub (pinned to aa36b38e69)
Solutions
- Retry the script — many failures are transient (CDN hiccups, rate limits).
- Check if the URL is reachable in a browser or with curl -I to distinguish 404 (permanent) from transient errors.
- If a vendor changed their URL scheme, update the pinned_browsers.py script to use the new URL pattern.
- Run the script from a network without proxies/firewalls that might block browser download endpoints.
Example fix
// before $ bazel run //scripts:pinned_browsers ValueError: Download unavailable (HTTP 404): https://... // after # Retry (transient): $ bazel run //scripts:pinned_browsers # If persistent, verify URL: $ curl -I 'https://...'
Defensive patterns
Strategy: retry
Validate before calling
import urllib3
http = urllib3.PoolManager()
r = http.request('HEAD', url)
if r.status != 200:
print(f'URL not available (HTTP {r.status}), deferring pinned_browsers run')
# do not run the script Type guard
null
Try / catch
try:
calculate_hash(url)
except ValueError as e:
# download unavailable; retry or report
print(f'Skipping: {e}') Prevention
- Run pinned_browsers.py from CI with retry logic for transient HTTP failures.
- Pre-check download URLs with HEAD requests before running the full script.
- Run from a network without restrictive proxies that block browser vendor CDNs.
When it happens
Trigger: Running the pinned_browsers.py script (via bazel run //scripts:pinned_browsers) when a download URL is temporarily or permanently unavailable: 404 (URL removed/changed), 403 (rate-limited or access denied), 500/502/503 (server error), or network connectivity issues during CI.
Common situations: Browser vendor (Google, Mozilla, Microsoft) temporarily takes down a download endpoint during a release transition; CDN rate limiting from too many CI runs; network proxy or firewall blocking the download; URL format changed upstream and the script has not been updated; transient network failure in CI.
Related errors
- Failed to download {url}: HTTP {r.status}
- Fetch failed (HTTP {response.status}): {url}
- No chromedriver download found for platform 'linux64'
- No chromedriver download found for platform 'mac-arm64'
- No Chrome download found for platform 'linux64'
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/316a43a5a80e9b5b.
Report an issue: GitHub.