A tested walkthrough for Amazon -- the right proxy type, 87% tested success rate, working code, and what to avoid to stay compliant.
An Amazon scraper pulls product titles, prices, ratings, and stock status from public product pages using residential rotating proxies routed through US IPs. Amazon runs a custom WAF that blocks datacenter ranges fast and serves an interstitial CAPTCHA to suspicious traffic, but KnoxProxy residential IPs held an 87% success rate on product-page requests during the last test cycle. This setup covers single price checks and full catalog pipelines pulling thousands of ASINs a day.
| Anti-bot system | Custom WAF with CAPTCHA challenges |
| Challenge types | Interstitial "Enter the characters you see" CAPTCHA, JavaScript fingerprint checks on page load, TLS and HTTP/2 header fingerprinting, IP reputation scoring across the datacenter/residential split, Session-level velocity checks that flag repetitive ASIN batch scraping patterns |
| Rate limit behavior | Escalates from soft throttling to a full CAPTCHA wall after roughly 15-20 rapid requests from a single IP; repeat offenders receive temporary IP-level blocks that can last several hours. Batch scraping Amazon across a long ASIN list trips this faster than single-page lookups, since the requests share a predictable pattern the WAF can key on. |
| Tested success rate | 87% |
"""
KnoxProxy scraper for Amazon product pages.
Parses Amazon product pages by ASIN (the ten-character product ID in
every /dp/{asin} URL) to extract title, price, rating, review count,
and availability. Includes a batch function for scraping a list of
ASINs without tripping Amazon's WAF, and CAPTCHA-aware retry logic.
"""
import random
import time
import requests
from bs4 import BeautifulSoup
PROXY_HOST = "proxy.knoxproxy.com"
PROXY_PORT = 10000 # residential rotating
PROXY_USER = "your_username"
PROXY_PASS = "your_password"
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
),
"Accept-Language": "en-US,en;q=0.9",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
}
def build_proxy_url(country: str = "us") -> str:
user = f"{PROXY_USER}-country-{country}"
return f"http://{user}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"
def fetch_amazon_product(asin: str, country: str = "us", max_retries: int = 3) -> dict:
"""Fetch and parse a single Amazon product page by ASIN, retrying
with a fresh proxy IP whenever the response is a CAPTCHA page."""
url = f"https://www.amazon.com/dp/{asin}"
proxy_url = build_proxy_url(country)
proxies = {"http": proxy_url, "https": proxy_url}
for attempt in range(1, max_retries + 1):
try:
resp = requests.get(url, headers=HEADERS, proxies=proxies, timeout=20)
if resp.status_code == 200 and "captcha" not in resp.text.lower():
return parse_amazon_page(resp.text, asin)
print(f"Attempt {attempt}: status {resp.status_code}, retrying with a new IP")
except requests.exceptions.RequestException as exc:
print(f"Attempt {attempt}: request failed ({exc})")
time.sleep(random.uniform(2, 5))
raise RuntimeError(f"Failed to fetch Amazon ASIN {asin} after {max_retries} attempts")
def parse_amazon_page(html: str, asin: str) -> dict:
soup = BeautifulSoup(html, "html.parser")
title_el = soup.select_one("#productTitle")
price_el = soup.select_one(".a-price .a-offscreen")
rating_el = soup.select_one("span.a-icon-alt")
review_count_el = soup.select_one("#acrCustomerReviewText")
availability_el = soup.select_one("#availability span")
return {
"asin": asin,
"title": title_el.get_text(strip=True) if title_el else None,
"price": price_el.get_text(strip=True) if price_el else None,
"rating": rating_el.get_text(strip=True) if rating_el else None,
"review_count": review_count_el.get_text(strip=True) if review_count_el else None,
"availability": availability_el.get_text(strip=True) if availability_el else None,
}
def scrape_asin_batch(asins: list[str], country: str = "us") -> list[dict]:
"""Batch scrape a list of Amazon ASINs one at a time with randomized
pacing and a fresh proxy IP per ASIN. This is the pattern that keeps
an amazon asin batch scraping tool under Amazon's rate-limit radar
instead of tripping a CAPTCHA wall on the fourth or fifth ASIN."""
results = []
for asin in asins:
try:
results.append(fetch_amazon_product(asin, country=country))
except RuntimeError as exc:
print(f"Skipping {asin}: {exc}")
results.append({"asin": asin, "error": str(exc)})
time.sleep(random.uniform(2, 5)) # pace requests between ASINs
return results
if __name__ == "__main__":
asin_list = ["B0BSHF7WHW", "B08N5WRWNW", "B0C6KKQ7ND"]
for row in scrape_asin_batch(asin_list):
print(row)
"""
KnoxProxy price-history tracker for Amazon products.
Runs the ASIN scraper on a schedule and writes each result to a local
SQLite table so price drops can be charted over days or weeks. Reuses
fetch_amazon_product() from amazon_scraper.py so parsing logic lives
in one place.
"""
import random
import sqlite3
import time
from datetime import datetime, timezone
from amazon_scraper import fetch_amazon_product
DB_PATH = "amazon_price_history.db"
def init_db(path: str = DB_PATH) -> None:
conn = sqlite3.connect(path)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS price_snapshots (
asin TEXT NOT NULL,
title TEXT,
price TEXT,
rating TEXT,
review_count TEXT,
availability TEXT,
checked_at TEXT NOT NULL
)
"""
)
conn.commit()
conn.close()
def save_snapshot(row: dict, path: str = DB_PATH) -> None:
conn = sqlite3.connect(path)
conn.execute(
"""
INSERT INTO price_snapshots
(asin, title, price, rating, review_count, availability, checked_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(
row.get("asin"),
row.get("title"),
row.get("price"),
row.get("rating"),
row.get("review_count"),
row.get("availability"),
datetime.now(timezone.utc).isoformat(),
),
)
conn.commit()
conn.close()
def track_asins(asins: list[str], country: str = "us") -> None:
"""Scrape each ASIN and store a timestamped row, building the
history an amazon price scraper dashboard reads from later. Run
this on a daily cron job for ongoing amazon price tracking."""
init_db()
for asin in asins:
try:
row = fetch_amazon_product(asin, country=country)
save_snapshot(row)
print(f"Saved snapshot for {asin}: {row.get('price')}")
except RuntimeError as exc:
print(f"Skipping {asin} this run: {exc}")
time.sleep(random.uniform(2, 5))
if __name__ == "__main__":
track_asins(["B0BSHF7WHW", "B08N5WRWNW"])
{
"asin": "B0BSHF7WHW",
"title": "Echo Dot (5th Gen) Smart Speaker with Alexa",
"price": "$29.99",
"rating": "4.7 out of 5 stars",
"review_count": "89,412",
"availability": "In Stock"
}Install requests and BeautifulSoup for HTTP requests and HTML parsing. Python's built-in sqlite3 module handles price-history storage later, so no extra install is needed for that part.
pip install requests beautifulsoup4Set your residential gateway credentials and target country as environment-friendly constants. The same credentials drive every request in this amazon scraper, from a single lookup to a full batch run.
PROXY_HOST = "proxy.knoxproxy.com"
PROXY_PORT = 10000 # residential rotating
PROXY_USER = "your_username"
PROXY_PASS = "your_password"Build the request URL from the ASIN, the ten-character product ID found in every Amazon product URL after /dp/. Scraping Amazon by ASIN instead of by search keyword gives a stable target that does not shift when Amazon changes its search ranking or page layout.
Parse the response HTML for the product title, current price, star rating, and review count. This is the core of any amazon product scraper: pull the fields a shopper sees on the page, not internal IDs or hidden metadata.
Loop over a list of ASINs one at a time with a randomized 2-5 second delay between requests and a fresh proxy IP on each pull. This turns a single-page script into a working amazon asin batch scraping tool that runs against hundreds of products a day without triggering the CAPTCHA wall.
Detect CAPTCHA pages by checking the response text for the word "captcha" and retry immediately with a new IP instead of waiting out the block on the same one. Proxy rotation, not raw request volume, decides whether an amazon scraper api integration keeps working past the first few hundred pulls.
Write each scrape result to a local SQLite table keyed by ASIN and timestamp. A few weeks of stored rows is enough to chart price drops and build the kind of amazon price scraper dashboard most shoppers and sellers actually want.
Amazon runs custom WAF with CAPTCHA challenges. The tested setup is residential rotating proxies, targeting uS residential IPs for amazon.com; match the proxy country to the marketplace TLD (co.uk, de, in, co.jp) you are targeting, with this rotation: New IP every 1-2 requests for single lookups; a fresh IP per ASIN when running an amazon asin batch scraping tool across a list. That combination held a 87% success rate on the Jul 1, 2026 test run.
The proxy is half the job — new IP every 1-2 requests for single lookups; a fresh IP per ASIN when running an amazon asin batch scraping tool across a list is what turns a working request into a repeatable one.
New IP every 1-2 requests for single lookups; a fresh IP per ASIN when running an amazon asin batch scraping tool across a list.
US residential IPs for amazon.com; match the proxy country to the marketplace TLD (co.uk, de, in, co.jp) you are targeting.
Amazon leans on interstitial "Enter the characters you see" CAPTCHA. Escalates from soft throttling to a full CAPTCHA wall after roughly 15-20 rapid requests from a single IP; repeat offenders receive temporary IP-level blocks that can last several hours. Batch scraping Amazon across a long ASIN list trips this faster than single-page lookups, since the requests share a predictable pattern the WAF can key on.
Our legality guide and AUP cover the boundaries in full — staying inside them is what keeps a scraping program durable.
Amazon's robots.txt permits crawling of most product pages, but its Conditions of Use separately prohibit automated data collection. Most amazon price scraper tools and price-tracking dashboards scrape public listing pages anyway, managing risk with pacing and proxy rotation rather than relying on explicit permission.
Residential rotating proxies work best because Amazon's WAF scores datacenter IP ranges more aggressively. Rotating IPs on every request, or every two requests, keeps any single address below the threshold that escalates from soft throttling to a full CAPTCHA wall after 15-20 rapid requests. Match the proxy country to the marketplace TLD you target.
Pace requests to 1-3 per second, randomize delays between 2 and 5 seconds, rotate residential IPs on every request, and send realistic browser headers including a current User-Agent and Accept-Language. Check each response for the word captcha and retry immediately from a fresh IP instead of waiting out a block, since rotation recovers most failed pulls.
Yes, review text and star ratings on the product page are publicly visible and safe to collect, but reviewer profile links and account-level data should be excluded to stay within a public-data-only scope. Amazon's Conditions of Use separately prohibit automated collection, so keep request volume modest and treat large-scale review pulls as a compliance gray area.
Loop through the ASIN list one item at a time, add a randomized 2-5 second delay between requests, and rotate to a fresh residential IP on every pull. An amazon asin batch scraping tool built this way holds up across hundreds of products instead of tripping a CAPTCHA wall after a handful.
Run the scraper on a schedule, such as a daily cron job, and write each result to a database table keyed by ASIN and timestamp. A simple SQLite table is enough to power an amazon price scraper dashboard that charts price drops over weeks.
The Python code above is a tested, working amazon scraper you can run as-is or extend with your own fields. It handles proxy rotation, retry logic, and batch scraping directly, so there's no separate service to configure before pulling product data.
residential proxies -- 87% tested success, instant activation, 14-day money-back guarantee.