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 AU egress with state delivery, postcode, en-AU content, AUD pricing, and the target’s GST display.

Quick answer: Choose an Australian residential route only when the job requires AU egress and the supplier documents its network class. Verify the exit, then test state delivery, postcode, page locale, AUD price, and GST display in the same target flow.
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
An Australian target can distinguish state or territory delivery even when the proxy exit is country-level. Keep AU, en-AU, the selected IANA timezone, state, four-digit postcode, AUD, and the target’s GST display as separate fields.
Choose a product against the Australian job, including the state delivery result, before comparing headline rates. Use these fields for both offers in a shortlist.
| Offer field | Buyer acceptance condition |
|---|---|
| Current AU and city entitlement | The exact account includes AU and Sydney or Perth when the job requires that city |
| Residential definition and sourcing | Documented network class; do not pay for mobile or city targeting unless the test needs it |
| Session and replacement rules | One route can cover the required product, delivery and cart sequence |
| No-match behavior | A missing city is reported distinctly or uses only a fallback allowed by the declared test |
| State delivery result | The target records the requested NSW or WA destination and the required eligibility, charge or delivery window |
| Workload and billing terms | Permitted target, traffic unit, retry charges, minimum purchase and expiry support the planned sample |
For a hypothetical Perth freight check, prefer an AU offer with suitable session continuity over a Sydney-only rotating offer when the target chooses freight by delivery address. If the job also requires Perth network egress, neither a country-only entitlement nor a browser timezone setting satisfies it. Compare the cost of complete delivery records, including failed attempts, before paying for greater location precision.
Use AU as the ISO 3166 country field and AUD as the ISO 4217 currency field. Use en-AU when the workflow requires Australian English and select a timezone from the IANA database, such as Australia/Sydney or Australia/Perth. The timezone belongs to the browser context; it is not evidence that the proxy exit is in that city.
Australia Post describes the postcode system as four-digit and assigns codes to delivery areas; locality boundaries are set by state and local authorities. The Australian Taxation Office describes GST as 10% on most goods and services sold or consumed in Australia. Record the target's tax display rather than adding GST to a price that may already include it or may be outside the relevant supply conditions.
For a price or catalog buyer, compare a named state fixture instead of one generic “Australia” row:
| Requirement | Example Australia fixture | Pass condition |
|---|---|---|
| Country exit | requested_country=AU |
A dated lookup reports AU and retains source and uncertainty |
| State and city | requested_state=NSW, requested_city=Sydney or WA, Perth |
The observed city or accepted metro matches the stated rule |
| Browser context | locale=en-AU, location-specific timezone |
The browser uses the intended locale and clock inputs |
| Delivery | Authorized Australian address with a four-digit postcode | The target accepts the selected state or territory context |
| Offer record | currency=AUD, amount, GST display, final URL |
Values come from the target observation, not from a provider claim |
For a hypothetical Sydney dispatch-cutoff test on an owned storefront, fix an NSW destination and capture times on either side of the merchant's declared local cutoff using Australia/Sydney. Accept when the delivery-window message changes according to that declared rule while SKU and destination remain fixed. Record UTC timestamps so the timing comparison is reproducible.
For a Perth freight-eligibility check, keep the same SKU but select an authorized WA address and Australia/Perth. Require the target's WA eligibility decision, freight charge or explicit refusal, and AUD/GST display. A default NSW shipping estimate fails the observation even with an AU exit. These are hypothetical test designs, not claims that a retailer has a particular cutoff or ships to either state. Buy city-level egress only when it is an additional requirement of the test.
The sample checks the IP echo and then opens the authorized target in the same browser context. It accepts the target only when the final navigation status matches TARGET_EXPECTED_STATUS and visible body text contains TARGET_BODY_MARKER. Neither check proves country egress, residential classification, or a localized offer.
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-AU"
TIMEZONE = "Australia/Sydney"
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-AU', 'timezone': 'Australia/Sydney'}
Save the example as australia-probe.py and run it after loading the environment values:
python australia-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.
Keep PROXY_SERVER, PROXY_USER, and PROXY_PASSWORD in the approved secret store or environment binding. Do not place them in a URL, source file, screenshot, or CI log. Compare the observed address with a named, dated geolocation or ASN lookup. MaxMind explains why city-level IP data needs an uncertainty field.
The code checks the configured target page response in the same context as the IP echo. For an Australian offer, compare the observed AU lookup, state and postcode delivery outcome, page locale, AUD price, GST display, and account state against the fixture.
An AU exit with a US delivery country and USD price is not an Australian offer. An en-AU page with AUD pricing can still reject the requested state or use an account-specific shipping rule. A redirect to login, an unavailable product, or a missing GST line is an observed outcome to classify, not an invitation to invent a total or repeat the request until it looks local.
| 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 |
| A postcode resolves to the wrong state or locality | Postcodes and locality boundaries can change | Check the target address with current Australia Post data and record the resolved state |
| A local page shows AUD but the delivery estimate is for another state | Currency and locale do not set the destination | Hold the authorized postcode and account fixed, then classify the state-specific result separately |
| The delivery cutoff changes unexpectedly | The target may use a different account, timezone, or capture time | Record UTC capture time and the target's displayed local cutoff; do not infer it from the proxy exit alone |
Residential, datacenter, and mobile routes represent different procurement decisions. Choose residential when the target or acceptance rule requires an end-user network class and the supplier documents its sourcing. A datacenter route can fit a server-side Australian job when residential identity is not required. Mobile is a separate product with its own inventory and terms; an AU residential selector does not satisfy it. Compare the options in the residential versus datacenter guide and mobile and ISP guide.
For a Sydney or Perth delivery workflow, hold one session while checking the product, state and postcode fields. Rotate only when a fresh exit is part of the test, and record whether the route change also changed the page, currency or delivery outcome. The rotation and sticky-session guide shows how to keep that variable visible.
Set the budget in job units: transferred traffic, attempts, retries and accepted records, with minimum purchase or expiry terms beside them. The residential buying guide and cost-per-successful-request guide keep an Australian quote tied to useful output rather than the lowest headline number.
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