Building Facebook & Amazon Data Extractors: A Guide


David Foster
Scraping Techniques
Public product listings, prices, and Page metadata are genuinely useful for market research, price monitoring, and brand analysis. The trick is collecting that data in a way that's technically sound and stays inside each platform's rules. This guide shows how to build two extractors — one for Amazon public product pages, one for public Facebook Pages — using Python, a headless browser, and rotating proxies, while being honest about where the boundaries are.
What web scraping actually involves
At its simplest, web scraping means sending HTTP requests, receiving HTML, and parsing out the fields you care about. In practice, modern sites like Amazon and Facebook render much of their content with JavaScript, so a raw HTML download often returns an empty shell. That's why serious scrapers reach for a real browser engine (Playwright or Puppeteer) that executes scripts before you read the DOM.
Python remains the most convenient language for this work thanks to Beautiful Soup for parsing, Scrapy for large crawls, and Playwright for rendering dynamic pages. Which one you pick depends on whether the page is static (Scrapy/requests) or JavaScript-heavy (Playwright).
Draw the line before you write a line of code
Scraping is not inherently illegal, but what you collect and how you use it can be. A few rules keep any project on solid ground:
Public data only. Collect what any visitor can see without logging in. Don't build tools that log into an account you don't own to reach private posts, friend lists, or messages — that violates platform terms and, in many jurisdictions, data-protection law.
Respect the terms and
robots.txt. Read each platform's terms of service and honor rate signals. If an official API exists (Amazon's Product Advertising API, Meta's Graph API), prefer it — it's the sanctioned path and usually more stable.Mind personal data. Regulations like the GDPR govern how you store and process anything that identifies a person. Aggregate, anonymize, and keep only what you need.
Be a polite guest. Throttle your requests, identify your bot in the user-agent where appropriate, and don't hammer servers. The goal is data collection, not disruption.
If a task can only be done by impersonating a real user to reach non-public content, that's your signal to stop and use the official API or a data-licensing agreement instead.
Building an Amazon public-data extractor
Amazon exposes a huge amount of public information: product titles, prices, ratings, review counts, and availability on listing pages. Because listing pages are largely server-rendered, you can often get away with plain HTTP requests plus Beautiful Soup. Two practical points: prices change constantly (so timestamp every capture), and you'll want to distribute requests across IPs to collect at scale without straining any single endpoint.
Here's a compact, self-contained extractor for a public product page. Route it through rotating residential proxies so requests come from diverse, ethically sourced IPs.
import csv
import time
import requests
from bs4 import BeautifulSoup
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"
),
"Accept-Language": "en-US,en;q=0.9",
}
# Evomi rotating residential endpoint (use your own credentials)
PROXY = {
"http": "http://USER:PASS@rp.evomi.com:1000",
"https": "http://USER:PASS@rp.evomi.com:1000",
}
def scrape_product(asin):
url = f"https://www.amazon.com/dp/{asin}"
resp = requests.get(url, headers=HEADERS, proxies=PROXY, timeout=20)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
def text_or_none(selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else None
return {
"asin": asin,
"title": text_or_none("#productTitle"),
"price": text_or_none(".a-price .a-offscreen"),
"rating": text_or_none("span.a-icon-alt"),
"reviews": text_or_none("#acrCustomerReviewText"),
"captured_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
}
def main(asins):
with open("products.csv", "w", newline="") as f:
writer = None
for asin in asins:
try:
row = scrape_product(asin)
if writer is None:
writer = csv.DictWriter(f, fieldnames=row.keys())
writer.writeheader()
writer.writerow(row)
print("OK", asin, row["price"])
except Exception as e:
print("FAIL", asin, e)
time.sleep(2) # be polite between requests
if __name__ == "__main__":
main(["B08N5WRWNW", "B07FZ8S74R"])Selectors on Amazon shift over time and vary by region, so build in fallbacks and log misses rather than crashing. For anything beyond a handful of pages, move to Scrapy so you get concurrency, retries, and pipelines out of the box. We cover that pattern in depth in our guide on scraping Amazon data at scale.
Building a Facebook public-Page extractor
For Facebook, keep the scope narrow and legitimate: public Page content that anyone can view without an account — a business's public posts, follower counts, or the "About" details a brand chose to publish. Do not attempt to log in to reach private data; that crosses a clear line. For anything richer, Meta's Graph API is the correct, supported route and gives you structured data with permission.
Public Pages are JavaScript-rendered, so a headless browser is the right tool. Rather than maintaining browser infrastructure and residential exit IPs yourself, you can point Playwright at Evomi's Scraping Browser — a managed cloud Chromium you connect to over WebSocket.
from playwright.sync_api import sync_playwright
# Managed cloud Chromium endpoint (Playwright / Puppeteer compatible)
WS_ENDPOINT = "wss://browser.evomi.com?token=YOUR_TOKEN"
def scrape_public_page(page_url):
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(WS_ENDPOINT)
page = browser.new_page()
page.goto(page_url, wait_until="networkidle", timeout=45000)
# Only read what a logged-out visitor can see
title = page.title()
headings = page.locator("h1, h2").all_inner_texts()
data = {
"url": page_url,
"title": title,
"public_headings": headings[:10],
}
browser.close()
return data
if __name__ == "__main__":
print(scrape_public_page("https://www.facebook.com/SomePublicBrandPage"))Because it's a real browser, the page loads exactly as a visitor sees it, which is what you want when the goal is collecting public information for research. Keep runs modest, cache what you've already fetched, and don't loop aggressively over the same Page.
Handling the hard parts: dynamic content and pacing
Two challenges dominate real projects. The first is JavaScript-rendered content — infinite-scroll feeds and lazily-loaded prices that aren't in the initial HTML. A browser engine solves this: wait for network idle, or wait for a specific selector to appear before you read the DOM.
The second is pacing and volume. Sites rate-limit to protect their servers, and that's a reasonable constraint to work within. Add delays between requests, cap concurrency, and spread traffic across a pool of IPs so you're a light, well-behaved visitor rather than a burst of load from one address. This is where a rotating proxy pool earns its keep — not to hide, but to distribute legitimate, low-intensity requests responsibly. If you're new to proxy rotation, our Facebook and Amazon scraper walkthrough pairs the concepts with working code.
Choosing the right proxies
The proxy type you pick shapes cost and reliability:
Proxy type | Best for | Evomi price |
|---|---|---|
Datacenter | High-volume public pages that don't need residential IPs | from $0.30/GB |
Residential | Consumer-facing sites, geo-specific results | from $0.49/GB |
Mobile | Mobile-first content and app-style endpoints | from $2.20/GB |
Static ISP | Stable, long-lived sessions on one IP | from $1/IP |
Evomi's pools are ethically sourced and Swiss-based, with free trials on residential, mobile, and datacenter plans. Before a big run, it's worth checking your setup with our free proxy tester and IP geolocation tools so you know exactly where your requests appear to originate.
Wrapping up
Building Amazon and Facebook data extractors comes down to three things: use the right engine for the page (requests/Scrapy for static, Playwright for dynamic), collect only public data within each platform's terms, and pace your requests through a reliable, ethically sourced proxy pool. Prefer official APIs where they exist — they're stable and sanctioned — and reserve scraping for genuinely public information. Do that, and you get durable, defensible data pipelines instead of brittle scripts that break the moment you push a boundary you shouldn't.
Public product listings, prices, and Page metadata are genuinely useful for market research, price monitoring, and brand analysis. The trick is collecting that data in a way that's technically sound and stays inside each platform's rules. This guide shows how to build two extractors — one for Amazon public product pages, one for public Facebook Pages — using Python, a headless browser, and rotating proxies, while being honest about where the boundaries are.
What web scraping actually involves
At its simplest, web scraping means sending HTTP requests, receiving HTML, and parsing out the fields you care about. In practice, modern sites like Amazon and Facebook render much of their content with JavaScript, so a raw HTML download often returns an empty shell. That's why serious scrapers reach for a real browser engine (Playwright or Puppeteer) that executes scripts before you read the DOM.
Python remains the most convenient language for this work thanks to Beautiful Soup for parsing, Scrapy for large crawls, and Playwright for rendering dynamic pages. Which one you pick depends on whether the page is static (Scrapy/requests) or JavaScript-heavy (Playwright).
Draw the line before you write a line of code
Scraping is not inherently illegal, but what you collect and how you use it can be. A few rules keep any project on solid ground:
Public data only. Collect what any visitor can see without logging in. Don't build tools that log into an account you don't own to reach private posts, friend lists, or messages — that violates platform terms and, in many jurisdictions, data-protection law.
Respect the terms and
robots.txt. Read each platform's terms of service and honor rate signals. If an official API exists (Amazon's Product Advertising API, Meta's Graph API), prefer it — it's the sanctioned path and usually more stable.Mind personal data. Regulations like the GDPR govern how you store and process anything that identifies a person. Aggregate, anonymize, and keep only what you need.
Be a polite guest. Throttle your requests, identify your bot in the user-agent where appropriate, and don't hammer servers. The goal is data collection, not disruption.
If a task can only be done by impersonating a real user to reach non-public content, that's your signal to stop and use the official API or a data-licensing agreement instead.
Building an Amazon public-data extractor
Amazon exposes a huge amount of public information: product titles, prices, ratings, review counts, and availability on listing pages. Because listing pages are largely server-rendered, you can often get away with plain HTTP requests plus Beautiful Soup. Two practical points: prices change constantly (so timestamp every capture), and you'll want to distribute requests across IPs to collect at scale without straining any single endpoint.
Here's a compact, self-contained extractor for a public product page. Route it through rotating residential proxies so requests come from diverse, ethically sourced IPs.
import csv
import time
import requests
from bs4 import BeautifulSoup
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"
),
"Accept-Language": "en-US,en;q=0.9",
}
# Evomi rotating residential endpoint (use your own credentials)
PROXY = {
"http": "http://USER:PASS@rp.evomi.com:1000",
"https": "http://USER:PASS@rp.evomi.com:1000",
}
def scrape_product(asin):
url = f"https://www.amazon.com/dp/{asin}"
resp = requests.get(url, headers=HEADERS, proxies=PROXY, timeout=20)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
def text_or_none(selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else None
return {
"asin": asin,
"title": text_or_none("#productTitle"),
"price": text_or_none(".a-price .a-offscreen"),
"rating": text_or_none("span.a-icon-alt"),
"reviews": text_or_none("#acrCustomerReviewText"),
"captured_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
}
def main(asins):
with open("products.csv", "w", newline="") as f:
writer = None
for asin in asins:
try:
row = scrape_product(asin)
if writer is None:
writer = csv.DictWriter(f, fieldnames=row.keys())
writer.writeheader()
writer.writerow(row)
print("OK", asin, row["price"])
except Exception as e:
print("FAIL", asin, e)
time.sleep(2) # be polite between requests
if __name__ == "__main__":
main(["B08N5WRWNW", "B07FZ8S74R"])Selectors on Amazon shift over time and vary by region, so build in fallbacks and log misses rather than crashing. For anything beyond a handful of pages, move to Scrapy so you get concurrency, retries, and pipelines out of the box. We cover that pattern in depth in our guide on scraping Amazon data at scale.
Building a Facebook public-Page extractor
For Facebook, keep the scope narrow and legitimate: public Page content that anyone can view without an account — a business's public posts, follower counts, or the "About" details a brand chose to publish. Do not attempt to log in to reach private data; that crosses a clear line. For anything richer, Meta's Graph API is the correct, supported route and gives you structured data with permission.
Public Pages are JavaScript-rendered, so a headless browser is the right tool. Rather than maintaining browser infrastructure and residential exit IPs yourself, you can point Playwright at Evomi's Scraping Browser — a managed cloud Chromium you connect to over WebSocket.
from playwright.sync_api import sync_playwright
# Managed cloud Chromium endpoint (Playwright / Puppeteer compatible)
WS_ENDPOINT = "wss://browser.evomi.com?token=YOUR_TOKEN"
def scrape_public_page(page_url):
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(WS_ENDPOINT)
page = browser.new_page()
page.goto(page_url, wait_until="networkidle", timeout=45000)
# Only read what a logged-out visitor can see
title = page.title()
headings = page.locator("h1, h2").all_inner_texts()
data = {
"url": page_url,
"title": title,
"public_headings": headings[:10],
}
browser.close()
return data
if __name__ == "__main__":
print(scrape_public_page("https://www.facebook.com/SomePublicBrandPage"))Because it's a real browser, the page loads exactly as a visitor sees it, which is what you want when the goal is collecting public information for research. Keep runs modest, cache what you've already fetched, and don't loop aggressively over the same Page.
Handling the hard parts: dynamic content and pacing
Two challenges dominate real projects. The first is JavaScript-rendered content — infinite-scroll feeds and lazily-loaded prices that aren't in the initial HTML. A browser engine solves this: wait for network idle, or wait for a specific selector to appear before you read the DOM.
The second is pacing and volume. Sites rate-limit to protect their servers, and that's a reasonable constraint to work within. Add delays between requests, cap concurrency, and spread traffic across a pool of IPs so you're a light, well-behaved visitor rather than a burst of load from one address. This is where a rotating proxy pool earns its keep — not to hide, but to distribute legitimate, low-intensity requests responsibly. If you're new to proxy rotation, our Facebook and Amazon scraper walkthrough pairs the concepts with working code.
Choosing the right proxies
The proxy type you pick shapes cost and reliability:
Proxy type | Best for | Evomi price |
|---|---|---|
Datacenter | High-volume public pages that don't need residential IPs | from $0.30/GB |
Residential | Consumer-facing sites, geo-specific results | from $0.49/GB |
Mobile | Mobile-first content and app-style endpoints | from $2.20/GB |
Static ISP | Stable, long-lived sessions on one IP | from $1/IP |
Evomi's pools are ethically sourced and Swiss-based, with free trials on residential, mobile, and datacenter plans. Before a big run, it's worth checking your setup with our free proxy tester and IP geolocation tools so you know exactly where your requests appear to originate.
Wrapping up
Building Amazon and Facebook data extractors comes down to three things: use the right engine for the page (requests/Scrapy for static, Playwright for dynamic), collect only public data within each platform's terms, and pace your requests through a reliable, ethically sourced proxy pool. Prefer official APIs where they exist — they're stable and sanctioned — and reserve scraping for genuinely public information. Do that, and you get durable, defensible data pipelines instead of brittle scripts that break the moment you push a boundary you shouldn't.

Author
David Foster
Proxy & Network Security Analyst
About Author
David is an expert in network security, web scraping, and proxy technologies, helping businesses optimize data extraction while maintaining privacy and efficiency. With a deep understanding of residential, datacenter, and rotating proxies, he explores how proxies enhance cybersecurity, bypass geo-restrictions, and power large-scale web scraping. David’s insights help businesses and developers choose the right proxy solutions for SEO monitoring, competitive intelligence, and anonymous browsing.



