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 guideCompare IN egress with page language, INR pricing, Asia/Kolkata time, and delivery acceptance for one target job.

Quick answer: Choose an India residential route only when the job requires IN egress and the supplier documents its network class. Verify the exit, then keep page language, INR pricing, Asia/Kolkata time, and destination acceptance as separate fields.
Audience: Proxy buyers and developers comparing a permitted market or delivery test. The examples use Python and Playwright; they do not teach general Python syntax.
Prerequisites:
http://host:port, https://host:port, or socks5://host:port form and a test account with a request or traffic limit. Set PROXY_SERVER. Playwright documents proxy username/password settings for HTTP(S) proxies, and Chromium supports no SOCKS5 authentication methods. Use socks5:// only when the supplier permits unauthenticated access; set PROXY_USER and PROXY_PASSWORD separately only for HTTP(S) proxy authentication. Load any credentials from an approved secret manager or environment binding. Playwright documents HTTP proxy authentication; Chromium documents unauthenticated SOCKS5 support.https://httpbin.org/ip through the selected route and to access the intended target.TARGET_URL on an HTTP or HTTPS page, TARGET_EXPECTED_STATUS set to its expected integer response status, and TARGET_BODY_MARKER set to non-sensitive visible text that should appear in that page. Provide all three through the environment; do not embed credentials in the target URL.Install the pinned Python package and its matching Chromium build in the active environment:
python -m pip install playwright==1.58.0
python -m playwright install chromium
Choose between offers on the exact job, rather than a national pool-size claim. Obtain these answers for each quoted product and keep them beside the target test.
| Purchase question | How it changes the decision |
|---|---|
| Does this account include IN and the required city now? | Country-only inventory fits a national catalog check; a New Delhi campaign test needs its declared city or metro match |
| How is residential defined and sourced? | Require the network class the job specifies; authenticated access alone is not residential evidence |
| How long can one session hold, and what causes replacement? | A Bengaluru product-to-delivery journey needs continuity across its pages; per-request rotation fits separate observations |
| What happens when no matching route exists? | Require a recognizable failure or an explicitly accepted fallback, so another city cannot silently pass |
| Are the target and workload permitted, and what is billed? | Compare traffic units, charged retries, minimum purchase and expiry using accepted records from the same sample |
As a hypothetical comparison, an IN country offer with session continuity can be sufficient for delivery availability driven by a Bengaluru PIN. A more expensive city selector adds value only if the job also requires Bengaluru egress. For a New Delhi city-targeted campaign, reverse that priority: reject country-only routing even if its per-GB quote is lower.
The Government of India's language policy identifies Hindi in Devanagari as the Union's official language and permits English for official purposes. That policy does not determine the language of a commercial page; record the target's observed result. Set browser time only when it belongs to the fixture and retain capture timestamps in UTC.
For a buyer comparing a national storefront, a useful fixture might look like this:
| Field | India test value | What must be observed |
|---|---|---|
| Country | requested_country=IN |
IP lookup returns a dated country result, with source and uncertainty |
| City | requested_city=New Delhi or the city required by the job |
The lookup reports the accepted city or metro rule; country alone is insufficient |
| Browser | locale=en-IN, timezone=Asia/Kolkata (IANA time-zone database) |
The browser sends the intended context |
| Language case | English page or an explicitly requested Hindi page | The target exposes the expected language or locale marker |
| Delivery | A permitted Indian address with a six-digit PIN code | The target accepts the selected delivery market; the Ministry of Communications describes the six-digit PIN system |
| Price | currency=INR, amount copied from the target |
The page field is recorded; no amount is invented or treated as ProxyLane pricing |
Set the language and delivery criteria before running either hypothetical buyer job:
| Job | Inputs to hold fixed | Acceptance condition |
|---|---|---|
| New Delhi campaign QA on an owned landing page | Named campaign, Hindi page variant, hi-IN, Asia/Kolkata, declared Delhi metro tolerance |
Observed exit meets that tolerance and the landing page displays the approved Hindi headline and campaign ID; an English default fails this job |
| Bengaluru delivery-catalog check | Same SKU and seller, English page, en-IN, authorized Bengaluru PIN, stable account and session |
Target records that PIN's stock or delivery outcome and an INR offer; a Delhi delivery selection fails even when the exit is IN |
For Bengaluru, an explicit “unavailable for this PIN” is a valid availability result; a login wall is incomplete. A purchase test passes only with an accepted destination and complete offer.
For the New Delhi Hindi fixture, change LOCALE in the sample to "hi-IN" and set TARGET_BODY_MARKER to the approved Hindi headline. The default "en-IN" example below covers the English-language fixture.
Playwright documents proxy settings at browser-context creation and separate locale and time-zone emulation. The script checks the exit IP and then navigates to the authorized target in the same browser context. It uses the /ip response contract documented by httpbin.
Warning: Each run makes a top-level request to httpbin and navigates to TARGET_URL. The target page may also trigger redirects and subresource requests, so total requests and traffic can exceed those two top-level checks; the supplier may bill according to its own documented units and receives the destinations. Start with a provider sandbox and an owned staging target when available. Without a sandbox, treat the run as a production test: use an authorized target, a low-limit test account, and a preset spend cap.
If an authenticated http:// proxy uses HTTP Basic, credentials travel without TLS protection; RFC 7617 recommends an external secure layer such as TLS. Use the provider's TLS-to-proxy endpoint when available. The proxy and target schemes are separate: an http:// target has no TLS, while an https:// target protects browser-to-target traffic inside the tunnel after setup. Neither upgrades an http:// browser-to-proxy hop or protects Basic credentials sent before the tunnel.
Keep credentials in environment bindings, never in either URL, source files, screenshots, or shared logs. If routing or usage differs from the quote, close the browser, stop the session or revoke its test credentials using the supplier's documented controls, and inspect usage before another request.
import asyncio
import json
import os
from urllib.parse import urlsplit
from playwright.async_api import async_playwright
# Configuration comes from the approved environment binding; never print these values.
PROXY_SERVER = os.getenv("PROXY_SERVER")
PROXY_USER = os.getenv("PROXY_USER")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")
TARGET_URL = os.getenv("TARGET_URL")
TARGET_EXPECTED_STATUS = os.getenv("TARGET_EXPECTED_STATUS")
TARGET_BODY_MARKER = os.getenv("TARGET_BODY_MARKER")
NAVIGATION_TIMEOUT_MS = 20000
BODY_MARKER_TIMEOUT_MS = 10000
LOCALE = "en-IN"
TIMEZONE = "Asia/Kolkata"
async def main():
if bool(PROXY_USER) != bool(PROXY_PASSWORD):
raise ValueError("Provide both proxy credentials or neither")
try:
proxy_parts = urlsplit(PROXY_SERVER or "")
proxy_port = proxy_parts.port
except ValueError as error:
raise ValueError("Set PROXY_SERVER to a documented host:port endpoint without credentials") from error
if (
proxy_parts.scheme not in {"http", "https", "socks5"}
or not proxy_parts.hostname
or not proxy_port
or proxy_parts.username is not None
or proxy_parts.password is not None
):
raise ValueError("Set PROXY_SERVER to a documented HTTP(S) or SOCKS5 endpoint without credentials")
if proxy_parts.scheme == "socks5" and (PROXY_USER or PROXY_PASSWORD):
raise ValueError("Use SOCKS5 without proxy credentials; this example supports credentials only for HTTP(S) proxies")
try:
target_parts = urlsplit(TARGET_URL or "")
except ValueError as error:
raise ValueError("Set TARGET_URL to a permitted HTTP(S) page without embedded credentials") from error
if (
target_parts.scheme not in {"http", "https"}
or not target_parts.hostname
or target_parts.username is not None
or target_parts.password is not None
):
raise ValueError("Set TARGET_URL to a permitted HTTP(S) page without embedded credentials")
try:
expected_status = int(TARGET_EXPECTED_STATUS or "")
except ValueError as error:
raise ValueError("Set TARGET_EXPECTED_STATUS to the expected integer status code") from error
if not 100 <= expected_status <= 599:
raise ValueError("Set TARGET_EXPECTED_STATUS to an HTTP status from 100 through 599")
if not TARGET_BODY_MARKER or not TARGET_BODY_MARKER.strip():
raise ValueError("Set TARGET_BODY_MARKER to non-sensitive visible text expected on the target page")
proxy = {"server": PROXY_SERVER}
if PROXY_USER:
proxy.update(username=PROXY_USER, password=PROXY_PASSWORD)
async with async_playwright() as playwright:
browser = await playwright.chromium.launch()
try:
context = await browser.new_context(
proxy=proxy, locale=LOCALE, timezone_id=TIMEZONE
)
try:
page = await context.new_page()
echo_response = await page.goto(
"https://httpbin.org/ip",
wait_until="domcontentloaded",
timeout=NAVIGATION_TIMEOUT_MS,
)
if echo_response is None or echo_response.status != 200:
raise RuntimeError("IP echo request failed")
echo_payload = json.loads(await page.locator("body").inner_text(timeout=BODY_MARKER_TIMEOUT_MS))
origin = echo_payload.get("origin")
if not isinstance(origin, str) or not origin:
raise RuntimeError("IP echo did not return an address")
target_response = await page.goto(
TARGET_URL,
wait_until="domcontentloaded",
timeout=NAVIGATION_TIMEOUT_MS,
)
if target_response is None or target_response.status != expected_status:
raise RuntimeError("Target response did not match TARGET_EXPECTED_STATUS")
marker = page.get_by_text(TARGET_BODY_MARKER, exact=False).first
await marker.wait_for(state="visible", timeout=BODY_MARKER_TIMEOUT_MS)
body_text = await page.locator("body").inner_text(
timeout=BODY_MARKER_TIMEOUT_MS
)
if TARGET_BODY_MARKER not in body_text:
raise RuntimeError("Target body did not contain TARGET_BODY_MARKER")
print({
"observed_exit": origin,
"target_status": target_response.status,
"body_marker_found": True,
"locale": LOCALE,
"timezone": TIMEZONE,
})
finally:
await context.close()
finally:
await browser.close()
asyncio.run(main())
Illustrative expected output (the address is redacted; the values are not a country or target measurement):
{'observed_exit': '<redacted public IP>', 'target_status': 200, 'body_marker_found': True, 'locale': 'en-IN', 'timezone': 'Asia/Kolkata'}
Save the example as india-probe.py and run it after loading the environment values:
python india-probe.py
Set PROXY_SERVER, TARGET_URL, TARGET_EXPECTED_STATUS, and TARGET_BODY_MARKER in the approved environment; set both proxy credentials only if required. Playwright's page navigation and locator wait use bounded timeouts here: 20,000 ms per navigation and 10,000 ms for visible marker text. The script opens the target in the same configured context after the IP echo, then closes the context. A timeout or status/marker mismatch fails the check. These response checks do not establish country or city egress, a residential network, a delivery address, or a purchasable offer. Compare the returned IP with a dated lookup and verify country-specific business fields in an authorized target workflow. Redact the IP and target details before sharing logs.
The code checks the configured target page response in the same context as the IP echo. For an Indian offer, compare the observed IN lookup, page language, delivery PIN and outcome, INR amount, and checkout eligibility with the fixture. An English response can pass an English-language test but does not prove that a Hindi variant exists.
| Symptom | Check | Next action |
|---|---|---|
| Proxy returns an authentication error | The endpoint or credential format may not match the quoted product | If the response is 407, confirm the server and separate credentials with the supplier’s official setup guide; do not copy username formats from another provider |
| The target keeps an English page when Hindi is required | Browser locale does not force a commercial page to offer Hindi | Record the returned language and fail the language requirement without changing the requested job |
| A six-digit PIN is rejected | The selected address may not match the target's service area | Check the authorized PIN in India Post’s post-office locator and keep the target's delivery result as the acceptance signal |
| The IP lookup reports IN but delivery resolves elsewhere | Network exit and delivery destination are independent | Preserve both fields; accept only the outcome required by the declared catalog or delivery test |
Residential, datacenter, and mobile solve different acceptance rules. Choose residential when the job requires an end-user network class and the supplier documents its sourcing. Choose datacenter when the target accepts a server-side route and the workload does not need a residential classification. Choose mobile only after the supplier identifies a mobile product with its own inventory and terms; an India residential label does not answer a mobile requirement. The residential versus datacenter guide and mobile and ISP guide give the comparison fields.
Compare the selected offer's retry charges and minimum purchase against the planned sample; the cost-per-successful-request guide explains the calculation.
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