Amazon Scraper API vs Proxy: Choose a Product Data Source
Compare seller APIs, licensed Amazon product data and proxy page checks by record, access scope and reuse rights.
Read guideConnect CloakBrowser to a proxy, choose session behavior by workload, verify the exit in the same browser, and clean up safely.

This walkthrough suits Python developers with an authorized proxy endpoint and permission to access the target. It requires Python 3.9 or newer. The tested environment was Python 3.12.0 on macOS 26.5.2 arm64 with CloakBrowser 0.5.11 and its free Chromium binary 145.0.7632.109.2.
Pass the proxy server and optional credentials to CloakBrowser's launch call. Open an IP-echo page and the target in the same browser page to check the route and content. This verifies those requests only; it does not promise that a target will allow later requests.
Install the tested Python wrapper from PyPI: cloakbrowser 0.5.11 using Python 3.9 or newer. The tested environment used Python 3.12.0, macOS 26.5.2 arm64, wrapper 0.5.11 and free Chromium 145.0.7632.109.2:
Caution: Exposed proxy credentials allow unauthorized traffic and charges. The upstream README estimates a first-launch Chromium download of about 200 MB; the vendor states MB, not MiB. The download consumes network bandwidth and remains in the local cache. The exit check and target request can incur proxy traffic charges.
Run in a disposable environment with temporary credentials, a low-volume route and an authorized target. Revoke temporary credentials after the check. The sample closes the browser in finally and creates no persistent profile.
python3.12 -m pip install "cloakbrowser==0.5.11"
Residential is a sensible choice when the permitted workflow depends on a documented residential or access-network signal, or when a region-sensitive page must be checked from the purchased route. Datacenter can be the better fit for open public pages when the target accepts cloud egress and throughput or cost matters more than that network property. Neither network label predicts whether the target will return the required record.
| Workload | Start with | Keep stable or change | Acceptance check |
|---|---|---|---|
| Public pages and independent records | Datacenter, if accepted by the target | One route per independent request | Expected title, status and fields |
| Region-sensitive pages | Residential only when that property is part of the purchased route | Keep the same route through related pages | Same-browser exit and expected locale or record |
| Login, pagination or checkout-like sequence | Whichever route the target and provider permit | Sticky session and persistent profile | Exit remains stable and state survives the sequence |
| Independent country or market observations | Route matching each observation | New session or provider-defined rotation between items | Record exit, final URL and field-level result |
CloakBrowser does not provide proxy rotation. Rotation belongs to the proxy provider's endpoint or session parameters, and the browser must be relaunched or reconfigured according to that provider's contract. Do not rotate between a login page, pagination request and detail page when those pages share state.
Set PROXY_SERVER to http://<HOST>:<PORT> for an HTTP proxy, where <HOST> is the provider hostname and <PORT> is its port. Supply the raw username and password separately through PROXY_USER and PROXY_PASSWORD; keep the server field credential-free. Use the provider-specified scheme for another supported protocol.
Save the following script as cloak-proxy-check.py and run it with python3.12 cloak-proxy-check.py. The official Python wrapper accepts a proxy URL or a Playwright-style object with server, bypass, username and password. Build that object from the runtime environment so the password never enters page code, a committed file or a log.
import os
from ipaddress import ip_address
from urllib.parse import urlsplit
from cloakbrowser import launch
PROXY_SERVER = os.getenv("PROXY_SERVER", "").strip()
PROXY_USER = os.getenv("PROXY_USER", "")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD", "")
EXIT_CHECK_URL = os.getenv("EXIT_CHECK_URL", "").strip()
EXPECTED_EXIT_MARKER = os.getenv("EXPECTED_EXIT_MARKER", "").strip()
TARGET_URL = os.getenv("TARGET_URL", "").strip()
EXPECTED_TARGET_MARKER = os.getenv("EXPECTED_TARGET_MARKER", "").strip()
NAVIGATION_TIMEOUT_MS = 20_000
BODY_TIMEOUT_MS = 5_000
def main() -> None:
required = {
"PROXY_SERVER": PROXY_SERVER,
"EXIT_CHECK_URL": EXIT_CHECK_URL,
"EXPECTED_EXIT_MARKER": EXPECTED_EXIT_MARKER,
"TARGET_URL": TARGET_URL,
"EXPECTED_TARGET_MARKER": EXPECTED_TARGET_MARKER,
}
missing = [name for name, value in required.items() if not value]
if missing:
raise SystemExit("Set required runtime settings: " + ", ".join(missing))
if bool(PROXY_USER) != bool(PROXY_PASSWORD):
raise SystemExit("Set both proxy credential variables or neither")
proxy = {"server": PROXY_SERVER}
if PROXY_USER:
proxy["username"] = PROXY_USER
proxy["password"] = PROXY_PASSWORD
browser = None
try:
browser = launch(proxy=proxy)
page = browser.new_page()
route = page.goto(
EXIT_CHECK_URL,
wait_until="domcontentloaded",
timeout=NAVIGATION_TIMEOUT_MS,
)
route_body = page.locator("body").inner_text()
observed_exit = ip_address(route_body.strip())
expected_exit = ip_address(EXPECTED_EXIT_MARKER)
route_ok = route is not None and route.status == 200 and observed_exit == expected_exit
if not route_ok:
raise ValueError("Exit response did not match the expected marker")
target = page.goto(
TARGET_URL,
wait_until="domcontentloaded",
timeout=NAVIGATION_TIMEOUT_MS,
)
target_marker = EXPECTED_TARGET_MARKER
target_body = page.locator("body").inner_text(timeout=BODY_TIMEOUT_MS)
data_ok = (
target is not None
and target.status == 200
and target_marker in target_body
)
if not data_ok:
raise ValueError("Target response did not contain the expected marker")
print({
"route_status": route.status,
"route_ok": route_ok,
"target_status": target.status,
"target_path": urlsplit(page.url).path,
"data_ok": True,
})
except Exception as error:
raise SystemExit(
f"Browser proxy check failed ({type(error).__name__}); verify the proxy and test URLs"
) from None
finally:
if browser is not None:
try:
browser.close()
except Exception:
raise SystemExit("Browser cleanup failed; remove only the task-owned process") from None
if __name__ == "__main__":
main()
Set EXIT_CHECK_URL to https://api.ipify.org, whose official documentation specifies a plain-text IPv4 response, or a trusted endpoint with that same response format. Set EXPECTED_EXIT_MARKER to the complete expected IPv4 address. The script compares the entire trimmed response with that value; a partial IP cannot pass. This checks the exit of that browser request. A provider's rotating endpoint may use another exit for the next request, including the target.
A successful local fixture run captured this output:
{'route_status': 200, 'route_ok': True, 'target_status': 200, 'target_path': '/item', 'data_ok': True}
The self-owned fixture uses plain HTTP, a documentation-reserved IP and a known target marker. It checks local browser-to-proxy routing and response validation only; it does not establish HTTPS tunneling, a residential exit or a live provider route.
Set EXPECTED_TARGET_MARKER to a distinctive expected record value, such as a product's exact SKU. Generic site text is insufficient. The target check establishes only HTTP 200 and the presence of that substring in the page body.
It does not extract or validate record fields; add those assertions before accepting records. Keep retained exit evidence redacted.
This article exercises the Python API only. The official JavaScript API reference is included for readers evaluating that wrapper; it was not run as part of this guide.
CloakBrowser also documents inline credential URLs; an environment-built object reduces accidental disclosure. Its optional geoip mode can derive timezone and locale from the proxy route, so treat that lookup as part of the route check. Source code routes SOCKS5 through Chrome's --proxy-server path.
Credentialed HTTP or HTTPS uses Chrome inline authentication only when the selected binary supports it; older platform binaries can fall back to Playwright's proxy object. Keep the protocol exactly as supplied by the proxy provider. Pass raw PROXY_USER and PROXY_PASSWORD values in object fields. Percent-encoding applies only when constructing inline credential URLs.
Each navigation has a 20-second timeout and target-body lookup has a 5-second timeout. These limits do not include the browser download or impose a total job deadline. The example performs no retry loop.
For a login or multi-page task, keep one browser and one proxy route for the related pages. If cookies and local storage must survive a process restart, CloakBrowser's launch_persistent_context() stores them in a profile directory. That directory contains sensitive data. Use a disposable profile for tests and remove it when no longer needed.
A persistent profile does not make a rotating proxy sticky. See the official persistent-context API and configure affinity using the supplier's documented session option.
| Observation | Inspect first | Next action |
|---|---|---|
| Binary or import fails | Wrapper version, platform and cache | Run python -m cloakbrowser info --json or npx cloakbrowser info |
| 407 or proxy authentication error | Protocol, username, password and URL encoding | Check the provider credential pair and the selected binary's auth path |
| Exit check fails in the browser | Proxy host, port, bypass and actual egress | Repeat the check in a clean browser and compare the route record |
| Exit passes but target data is wrong | Final URL, status, locale and required field | Inspect redirects, cookies and page content separately |
| Exit changes mid-sequence | Provider session or rotation policy | Keep a sticky route for related pages or split the job |
| Browser remains after an exception | Missing close path | Put browser.close() or context.close() in finally and remove only task-owned temporary profiles |
The official README lists wrapper 0.5.11 and separate Chromium versions by platform and license tier. In the test run for this article, python -m cloakbrowser info --json reported wrapper 0.5.11, free binary 145.0.7632.109.2 and successful launch on macOS arm64.
The bundled baseline, free binary and Pro build are distinct. Check the selected build with python -m cloakbrowser info --json; the reported version can change as the wrapper and license channel move.
The Python and JavaScript wrappers are MIT licensed. The compiled browser binary has a separate license, and its terms call the third-party distribution permission an OEM/SaaS license for bundling, embedding or providing browser functionality to customers.
The official /free path and paid plans describe different access routes, so verify the entitlement before packaging the binary into a service. The proxy route, browser state and target permission remain separate decisions.
For the network classification decision, see the residential versus datacenter guide. For session policy, read the rotation and sticky sessions guide. The Playwright proxy guide, browser diagnostics guide and 407 troubleshooting guide cover the next checks when the route does not behave as expected.
Scale your workflows with the tools you already use. Rotating or sticky sessions up to 72 hours.
Compare seller APIs, licensed Amazon product data and proxy page checks by record, access scope and reuse rights.
Read guideChoose the right anti-detect browser proxy guide, map the shared verification steps, and keep account access separate from the network route.
Read guideOur picks for market research: ProxyLane for small, intermittent projects, plus options for regional tracking, monthly collection and managed extraction.
Read guide