Scrape Amazon product listings
Search Amazon for a keyword and extract product titles, prices, ratings, and links from the results page.
- A Browserless API token from your account dashboard
Steps
Amazon aggressively blocks automated browsers with CAPTCHAs and fingerprinting. A plain HTTP request or standard headless browser returns a bot-detection page instead of product data. The examples below search for "wireless headphones" and route through stealth mode with a residential proxy to bypass Amazon's protections.
Amazon updates its markup frequently. If .s-result-item or nested selectors stop returning results, inspect the live page with browser DevTools to find the current element names.
- AI Agent
- REST API
- Frameworks
- BQL
Use the Browserless MCP server to scrape product listings from Amazon from any MCP-compatible AI agent (Claude Desktop, Cursor, Windsurf, ChatGPT, etc.).
1. Connect the MCP server
Send this prompt to your AI agent to install the Browserless MCP server:
Go to https://github.com/browserless/browserless-mcp/blob/main/install.md
and follow the instructions to install the Browserless MCP server
for my client.
2. Scrape Amazon
Use browserless_smartscraper. It handles Amazon's bot protection automatically.
Use the browserless_smartscraper tool to scrape product listings
from https://www.amazon.com/s?k=wireless+headphones
and return the results as markdown
Send the BQL mutation over HTTP to the stealth endpoint. No browser library or BQL IDE required.
- cURL
- JavaScript
- Python
- Java
- C#
1. Send the request
curl -X POST \
"https://production-sfo.browserless.io/stealth/bql?token=YOUR_API_TOKEN_HERE&proxy=residential&proxyCountry=us" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation ScrapeAmazon { goto(url: \"https://www.amazon.com/s?k=wireless+headphones\", waitUntil: networkIdle) { status } waitForSelector(selector: \"div.s-result-item[data-asin]\", timeout: 15000) { time } products: mapSelector(selector: \"div.s-result-item[data-asin]\") { asin: attribute(name: \"data-asin\") { value } title: mapSelector(selector: \"h2 span\") { innerText } price: mapSelector(selector: \".a-price .a-offscreen\") { innerText } rating: mapSelector(selector: \".a-icon-alt\") { innerText } reviewCount: mapSelector(selector: \".a-size-base.s-underline-text\") { innerText } link: mapSelector(selector: \"h2 a\") { href: attribute(name: \"href\") { value } } } }",
"variables": {}
}'
2. Check the output
{
"data": {
"goto": { "status": 200 },
"waitForSelector": { "time": 2845 },
"products": [
{
"asin": { "value": "B0BT35LT8S" },
"title": [{ "innerText": "Sony WH-1000XM5 Wireless Noise Canceling Headphones" }],
"price": [{ "innerText": "$278.00" }],
"rating": [{ "innerText": "4.6 out of 5 stars" }],
"reviewCount": [{ "innerText": "12,847" }],
"link": [{ "href": { "value": "/dp/B0BT35LT8S" } }]
},
{
"asin": { "value": "B09WX4GJ1G" },
"title": [{ "innerText": "Apple AirPods Max Wireless Over-Ear Headphones" }],
"price": [{ "innerText": "$449.99" }],
"rating": [{ "innerText": "4.7 out of 5 stars" }],
"reviewCount": [{ "innerText": "8,234" }],
"link": [{ "href": { "value": "/dp/B09WX4GJ1G" } }]
}
]
}
}
1. Send the request
const query = `mutation ScrapeAmazon {
goto(url: "https://www.amazon.com/s?k=wireless+headphones", waitUntil: networkIdle) {
status
}
waitForSelector(selector: "div.s-result-item[data-asin]", timeout: 15000) {
time
}
products: mapSelector(selector: "div.s-result-item[data-asin]") {
asin: attribute(name: "data-asin") { value }
title: mapSelector(selector: "h2 span") { innerText }
price: mapSelector(selector: ".a-price .a-offscreen") { innerText }
rating: mapSelector(selector: ".a-icon-alt") { innerText }
reviewCount: mapSelector(selector: ".a-size-base.s-underline-text") { innerText }
link: mapSelector(selector: "h2 a") {
href: attribute(name: "href") { value }
}
}
}`;
const response = await fetch(
'https://production-sfo.browserless.io/stealth/bql?token=YOUR_API_TOKEN_HERE&proxy=residential&proxyCountry=us',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables: {} }),
}
);
const { data } = await response.json();
console.log(JSON.stringify(data.products, null, 2));
2. Check the output
[
{
"asin": { "value": "B0BT35LT8S" },
"title": [{ "innerText": "Sony WH-1000XM5 Wireless Noise Canceling Headphones" }],
"price": [{ "innerText": "$278.00" }],
"rating": [{ "innerText": "4.6 out of 5 stars" }],
"reviewCount": [{ "innerText": "12,847" }],
"link": [{ "href": { "value": "/dp/B0BT35LT8S" } }]
},
{
"asin": { "value": "B09WX4GJ1G" },
"title": [{ "innerText": "Apple AirPods Max Wireless Over-Ear Headphones" }],
"price": [{ "innerText": "$449.99" }],
"rating": [{ "innerText": "4.7 out of 5 stars" }],
"reviewCount": [{ "innerText": "8,234" }],
"link": [{ "href": { "value": "/dp/B09WX4GJ1G" } }]
}
]
1. Install dependencies
pip install requests
2. Send the request
import requests
query = """
mutation ScrapeAmazon {
goto(url: "https://www.amazon.com/s?k=wireless+headphones", waitUntil: networkIdle) {
status
}
waitForSelector(selector: "div.s-result-item[data-asin]", timeout: 15000) {
time
}
products: mapSelector(selector: "div.s-result-item[data-asin]") {
asin: attribute(name: "data-asin") { value }
title: mapSelector(selector: "h2 span") { innerText }
price: mapSelector(selector: ".a-price .a-offscreen") { innerText }
rating: mapSelector(selector: ".a-icon-alt") { innerText }
reviewCount: mapSelector(selector: ".a-size-base.s-underline-text") { innerText }
link: mapSelector(selector: "h2 a") {
href: attribute(name: "href") { value }
}
}
}
"""
response = requests.post(
'https://production-sfo.browserless.io/stealth/bql',
params={
'token': 'YOUR_API_TOKEN_HERE',
'proxy': 'residential',
'proxyCountry': 'us',
},
json={'query': query, 'variables': {}},
)
data = response.json()['data']
for product in data['products']:
title = product['title'][0]['innerText']
price = product['price'][0]['innerText'] if product['price'] else 'N/A'
rating = product['rating'][0]['innerText'] if product['rating'] else 'N/A'
print(f'{title} | {price} | {rating}')
3. Check the output
Sony WH-1000XM5 Wireless Noise Canceling Headphones | $278.00 | 4.6 out of 5 stars
Apple AirPods Max Wireless Over-Ear Headphones | $449.99 | 4.7 out of 5 stars
1. Send the request
import java.net.URI;
import java.net.http.*;
String token = "YOUR_API_TOKEN_HERE";
String endpoint = "https://production-sfo.browserless.io/stealth/bql?token=" + token
+ "&proxy=residential&proxyCountry=us";
String query = "mutation ScrapeAmazon {"
+ " goto(url: \\\"https://www.amazon.com/s?k=wireless+headphones\\\", waitUntil: networkIdle) { status }"
+ " waitForSelector(selector: \\\"div.s-result-item[data-asin]\\\", timeout: 15000) { time }"
+ " products: mapSelector(selector: \\\"div.s-result-item[data-asin]\\\") {"
+ " asin: attribute(name: \\\"data-asin\\\") { value }"
+ " title: mapSelector(selector: \\\"h2 span\\\") { innerText }"
+ " price: mapSelector(selector: \\\".a-price .a-offscreen\\\") { innerText }"
+ " rating: mapSelector(selector: \\\".a-icon-alt\\\") { innerText }"
+ " reviewCount: mapSelector(selector: \\\".a-size-base.s-underline-text\\\") { innerText }"
+ " link: mapSelector(selector: \\\"h2 a\\\") { href: attribute(name: \\\"href\\\") { value } }"
+ " }"
+ " }";
String payload = "{\"query\": \"" + query + "\", \"variables\": {}}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
2. Check the output
{
"data": {
"goto": { "status": 200 },
"waitForSelector": { "time": 2845 },
"products": [
{
"asin": { "value": "B0BT35LT8S" },
"title": [{ "innerText": "Sony WH-1000XM5 Wireless Noise Canceling Headphones" }],
"price": [{ "innerText": "$278.00" }],
"rating": [{ "innerText": "4.6 out of 5 stars" }]
}
]
}
}
1. Send the request
using System.Net.Http;
using System.Text;
using System.Text.Json;
string token = "YOUR_API_TOKEN_HERE";
string endpoint = $"https://production-sfo.browserless.io/stealth/bql?token={token}&proxy=residential&proxyCountry=us";
var payload = new
{
query = @"mutation ScrapeAmazon {
goto(url: ""https://www.amazon.com/s?k=wireless+headphones"", waitUntil: networkIdle) { status }
waitForSelector(selector: ""div.s-result-item[data-asin]"", timeout: 15000) { time }
products: mapSelector(selector: ""div.s-result-item[data-asin]"") {
asin: attribute(name: ""data-asin"") { value }
title: mapSelector(selector: ""h2 span"") { innerText }
price: mapSelector(selector: "".a-price .a-offscreen"") { innerText }
rating: mapSelector(selector: "".a-icon-alt"") { innerText }
reviewCount: mapSelector(selector: "".a-size-base.s-underline-text"") { innerText }
link: mapSelector(selector: ""h2 a"") {
href: attribute(name: ""href"") { value }
}
}
}",
variables = new { },
};
using (HttpClient httpClient = new HttpClient())
{
var content = new StringContent(
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync(endpoint, content);
string body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
2. Check the output
{
"data": {
"goto": { "status": 200 },
"waitForSelector": { "time": 2845 },
"products": [
{
"asin": { "value": "B0BT35LT8S" },
"title": [{ "innerText": "Sony WH-1000XM5 Wireless Noise Canceling Headphones" }],
"price": [{ "innerText": "$278.00" }],
"rating": [{ "innerText": "4.6 out of 5 stars" }]
}
]
}
}
Connect through stealth mode and a residential proxy so Amazon sees traffic from a real browser, then read product data from the rendered search results.
- Puppeteer
- Playwright
1. Install dependencies
npm install puppeteer-core
2. Connect and scrape
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
browserWSEndpoint:
'wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE&proxy=residential&proxyCountry=us',
});
try {
const page = await browser.newPage();
await page.goto('https://www.amazon.com/s?k=wireless+headphones', {
waitUntil: 'networkidle2',
});
await page.waitForSelector('div.s-result-item[data-asin]');
const products = await page.evaluate(() =>
Array.from(document.querySelectorAll('div.s-result-item[data-asin]'))
.filter((el) => el.getAttribute('data-asin'))
.map((el) => ({
asin: el.getAttribute('data-asin'),
title: el.querySelector('h2 span')?.innerText?.trim() ?? '',
price: el.querySelector('.a-price .a-offscreen')?.innerText?.trim() ?? '',
rating: el.querySelector('.a-icon-alt')?.innerText?.trim() ?? '',
}))
);
console.log(JSON.stringify(products, null, 2));
} finally {
await browser.close();
}
3. Check the output
Run with node scrape-amazon.mjs. Each object has asin, title, price, and rating fields.
[
{
"asin": "B0BT35LT8S",
"title": "Sony WH-1000XM5 Wireless Noise Canceling Headphones",
"price": "$278.00",
"rating": "4.6 out of 5 stars"
}
]
1. Install dependencies
npm install playwright-core
2. Connect and scrape
import { chromium } from 'playwright-core';
const browser = await chromium.connectOverCDP(
'wss://production-sfo.browserless.io?token=YOUR_API_TOKEN_HERE&stealth&proxy=residential&proxyCountry=us'
);
try {
const context = browser.contexts()[0];
const page = await context.newPage();
await page.goto('https://www.amazon.com/s?k=wireless+headphones', {
waitUntil: 'networkidle',
});
await page.waitForSelector('div.s-result-item[data-asin]');
const products = await page.evaluate(() =>
Array.from(document.querySelectorAll('div.s-result-item[data-asin]'))
.filter((el) => el.getAttribute('data-asin'))
.map((el) => ({
asin: el.getAttribute('data-asin'),
title: el.querySelector('h2 span')?.innerText?.trim() ?? '',
price: el.querySelector('.a-price .a-offscreen')?.innerText?.trim() ?? '',
rating: el.querySelector('.a-icon-alt')?.innerText?.trim() ?? '',
}))
);
console.log(JSON.stringify(products, null, 2));
} finally {
await browser.close();
}
3. Check the output
Run with node scrape-amazon.mjs. Each object has asin, title, price, and rating fields.
[
{
"asin": "B0BT35LT8S",
"title": "Sony WH-1000XM5 Wireless Noise Canceling Headphones",
"price": "$278.00",
"rating": "4.6 out of 5 stars"
}
]
1. Write the mutation
Navigate to Amazon's search results, wait for product cards to load, then extract titles, prices, ratings, and ASINs. We use /stealth/bql because Amazon's bot detection blocks standard headless browsers.
mutation ScrapeAmazon {
goto(url: "https://www.amazon.com/s?k=wireless+headphones", waitUntil: networkIdle) {
status
}
waitForSelector(selector: "div.s-result-item[data-asin]", timeout: 15000) {
time
}
products: mapSelector(selector: "div.s-result-item[data-asin]") {
asin: attribute(name: "data-asin") { value }
title: mapSelector(selector: "h2 span") { innerText }
price: mapSelector(selector: ".a-price .a-offscreen") { innerText }
rating: mapSelector(selector: ".a-icon-alt") { innerText }
reviewCount: mapSelector(selector: ".a-size-base.s-underline-text") { innerText }
link: mapSelector(selector: "h2 a") {
href: attribute(name: "href") { value }
}
}
}
2. Run it
Paste into the BQL IDE and click Run.
3. Check the output
{
"data": {
"goto": { "status": 200 },
"waitForSelector": { "time": 2845 },
"products": [
{
"asin": { "value": "B0BT35LT8S" },
"title": [{ "innerText": "Sony WH-1000XM5 Wireless Noise Canceling Headphones" }],
"price": [{ "innerText": "$278.00" }],
"rating": [{ "innerText": "4.6 out of 5 stars" }],
"reviewCount": [{ "innerText": "12,847" }],
"link": [{ "href": { "value": "/dp/B0BT35LT8S" } }]
},
{
"asin": { "value": "B09WX4GJ1G" },
"title": [{ "innerText": "Apple AirPods Max Wireless Over-Ear Headphones" }],
"price": [{ "innerText": "$449.99" }],
"rating": [{ "innerText": "4.7 out of 5 stars" }],
"reviewCount": [{ "innerText": "8,234" }],
"link": [{ "href": { "value": "/dp/B09WX4GJ1G" } }]
}
]
}
}
Next steps
- Scrape Etsy Product Listings -- scrape another e-commerce platform with stealth mode
- Scrape Structured Data -- extract data from other sites using the
/scrapeendpoint - Solving Cloudflare Challenges -- bypass Cloudflare protection on other targets