Summary
When a system copy of libcurl-impersonate older than curl-impersonate v2.1.0 is installed at one of the auto-detected paths, every request using the chrome alias fails with:
ImpersonateError: Impersonating chrome150 is not supported
impers 0.1.1 resolves chrome to chrome150 (NATIVE_TARGET_ALIASES in fingerprints.ts) and pins curl-impersonate v2.1.1, which supports that target. But resolveLibrary() in ffi/loader.ts checks the well-known system paths (/opt/homebrew/lib, /usr/local/lib, /usr/lib, etc.) before falling back to downloading the pinned version. A pre-v2.1.0 copy found there, for example from homebrew or a distro package, wins the resolution and then rejects chrome150, which was only added upstream in curl-impersonate v2.1.0 (2026-08-08). The default alias failing means the library is broken out of the box on such machines.
Reproduction
With impers 0.1.1 on linux-x64 and the real v2.0.0 release library:
LIBCURL_IMPERSONATE_PATH=/path/to/v2.0.0/libcurl-impersonate.so node -e "
import('impers').then(async m => {
for (const t of ['chrome', 'chrome146', 'chrome142', 'firefox']) {
try { const r = await m.get('https://example.com', { impersonate: t }); console.log(t, r.status); }
catch (e) { console.log(t, e.name + ':', e.message); }
}
});"
Output:
chrome ImpersonateError: Impersonating chrome150 is not supported
chrome146 200
chrome142 200
firefox 200
The env var stands in for the auto-detection here, but the effect is identical when the old library sits at a searched system path. Two users hit exactly this in the wild through a downstream tool (macOS arm64 with homebrew, Arch with an older packaged build): only-cli/oc#40.
Suggested fixes
Either of these would resolve it, and they compose:
- When the resolved target is rejected by the loaded native library (CURLE_BAD_FUNCTION_ARGUMENT from
curl_easy_impersonate), have alias resolution fall back to the newest target the library does support instead of throwing. Explicitly requested targets like chrome150 could still throw, but a generic alias like chrome expresses "a current Chrome", not a specific version.
- Prefer the pinned, known-good download over an auto-detected system library, or at least verify that a system library found first actually supports the targets the current alias table maps to before committing to it.
Happy to provide more details or test a branch.
Summary
When a system copy of libcurl-impersonate older than curl-impersonate v2.1.0 is installed at one of the auto-detected paths, every request using the
chromealias fails with:impers 0.1.1 resolves
chrometochrome150(NATIVE_TARGET_ALIASESinfingerprints.ts) and pins curl-impersonate v2.1.1, which supports that target. ButresolveLibrary()inffi/loader.tschecks the well-known system paths (/opt/homebrew/lib,/usr/local/lib,/usr/lib, etc.) before falling back to downloading the pinned version. A pre-v2.1.0 copy found there, for example from homebrew or a distro package, wins the resolution and then rejectschrome150, which was only added upstream in curl-impersonate v2.1.0 (2026-08-08). The default alias failing means the library is broken out of the box on such machines.Reproduction
With impers 0.1.1 on linux-x64 and the real v2.0.0 release library:
Output:
The env var stands in for the auto-detection here, but the effect is identical when the old library sits at a searched system path. Two users hit exactly this in the wild through a downstream tool (macOS arm64 with homebrew, Arch with an older packaged build): only-cli/oc#40.
Suggested fixes
Either of these would resolve it, and they compose:
curl_easy_impersonate), have alias resolution fall back to the newest target the library does support instead of throwing. Explicitly requested targets likechrome150could still throw, but a generic alias likechromeexpresses "a current Chrome", not a specific version.Happy to provide more details or test a branch.