puppeteer-sharp
puppeteer-sharp copied to clipboard
BrowserTag for Firefox download doesn't work.
Using BrowserFetcher, when trying to download Firefox, it fails to resolve the BaseUrl for non Nightly versions.
Getting the following exception:
PuppeteerSharp.PuppeteerException: 'Failed to download Firefox for Win64 from https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/firefox-140.0b3.en-US.win64.zip'
I tried to get BrowserTag.Stable but I got a failure message that showed a nightly url.
Looking through the code, it seems Firefox.ResolveDownloadUrl calls upon Firefox.ParseBuildId to figure out the Channel the BuildId belongs to.
This function seems to somehow use the FirefoxChannel enum values to figure out which version the BuildId comes from, but I don't see how.
Stable = 0, DevEdition = 4
private static (FirefoxChannel Channel, string BuildId) ParseBuildId(string buildId)
{
// Iterate through all the FirefoxChannel enum values as string
foreach (var value in EnumHelper.GetValues<FirefoxChannel>().Select(v => v.ToValueString()))
{
if (buildId.StartsWith(value, StringComparison.OrdinalIgnoreCase))
{
buildId = buildId.Substring(value.Length + 1);
return (value.ToEnum<FirefoxChannel>(), buildId);
}
}
return (FirefoxChannel.Nightly, buildId);
}
For example, the latest versions are (json):
FIREFOX_AURORA | ""
FIREFOX_DEVEDITION | "140.0b3"
FIREFOX_ESR | "128.11.0esr"
FIREFOX_ESR115 | "115.24.0esr"
FIREFOX_ESR_NEXT | ""
FIREFOX_NIGHTLY | "141.0a1"
LAST_MERGE_DATE | "2025-05-26"
LAST_RELEASE_DATE | "2025-05-27"
LAST_SOFTFREEZE_DATE | "2025-05-22"
LAST_STRINGFREEZE_DATE | "2025-05-23"
LATEST_FIREFOX_DEVEL_VERSION | "140.0b3"
LATEST_FIREFOX_OLDER_VERSION | "3.6.28"
LATEST_FIREFOX_RELEASED_DEVEL_VERSION | "140.0b3"
LATEST_FIREFOX_VERSION | "139.0.1"
NEXT_MERGE_DATE | "2025-06-23"
NEXT_RELEASE_DATE | "2025-06-24"
NEXT_SOFTFREEZE_DATE | "2025-06-19"
NEXT_STRINGFREEZE_DATE | "2025-06-20"
Taking Stable = "139.0.1" and Dev = "140.0b3" and given that the condition in the code above is a StartsWith, it most likely fails to do that check.
As far as I understand, it expects the Name of the enum option to be present in the beginning of the BuildId. That means "Stable" and "DevEdition"
But in ResolveBuildIdAsync(BrowserTag.Stable) , we get the above json data as a dictionary and the BuildId comes from the value.
So the BuildId, in essence, comes out of ResolveBuildIdAsync as just the version, e.g. "140.0b3", so it will not match anything using StartsWith. Even if you test it against the names or the values of the FirefoxChannel options.
Seeing as there's no match in that for loop, it uses the fallback which is Nightly.
What confuses me is that DownloadAsync starts with a BrowserTag (or defaults to Nightly) which tells it what to look for. It first looks up the last version based on that BrowserTag (which in the process of looking up the version, it also gets transformed into FirefoxChannel in ResolveBuildIdAsync) but then DownloadAsync is called with the BuildId without the BrowserTag. And maybe there's a way to parse the version into the FirefoxChannel, but it's not dead simple. On the other hand doing this, following the same logic as ResolveBuildIdAsync, seems easier:
switch (Browser)
{
case SupportedBrowser.Firefox:
return tag switch
{
BrowserTag.Latest => Firefox.ResolveURLFirefox(Channel.Nightly,..........),
BrowserTag.Beta => Firefox.ResolveURLFirefox(Channel.Beta,..........),
BrowserTag.Nightly => Firefox.ResolveURLFirefox(Channel.Nightly,..........),
BrowserTag.DevEdition => Firefox.ResolveURLFirefox(Channel.DevEdition,..........),
BrowserTag.Stable => Firefox.ResolveURLFirefox(Channel.Stable,..........),
BrowserTag.Esr => Firefox.ResolveURLFirefox(Channel.Esr,..........),
_ => throw new PuppeteerException($"{tag} is not supported for {Browser}. Use 'latest' instead."),
};
case SupportedBrowser.Chrome:
return tag switch
Was there a reason not to reuse the logic from above and try to make sense of it all just with the BuildId?
We could fix that. The main issue is that we need to finish Bidi support before using a Stable version, because Firefox doesn't support CDP now. So, using Firefox stable won't work.