What are common web scraping tools?
ScrapingThe right scraping tool depends on one question: does the data you need exist in the raw HTML, or does it only appear after JavaScript runs? Picking a heavyweight browser tool for a static page wastes resources; picking a lightweight parser for a JS-rendered page returns nothing.
Common mistake
Reaching for a full browser automation tool by default, even for static HTML:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/static-blog-post") # plain server-rendered HTML
title = page.text_content("h1")
browser.close()
This launches a full Chromium process, waits for a network idle state, and tears it down — for content that was in the initial HTTP response the whole time. At any real scale, that's 10-50x the latency and memory cost of a plain HTTP request.
The fix
Match the tool to how the page renders. For static or server-rendered HTML, a plain HTTP request plus a parser is enough:
import requests
from bs4 import BeautifulSoup
html = requests.get("https://example.com/static-blog-post").text
title = BeautifulSoup(html, "html.parser").select_one("h1").get_text(strip=True)
For pages that build content client-side, a headless browser is required — but check the network tab first, since many "JS-heavy" pages are just calling a JSON API you can hit directly:
resp = requests.get("https://example.com/api/products?page=1")
products = resp.json()["items"] # often faster and more stable than rendering
If no such API exists, Playwright or Puppeteer render the page and expose the final DOM:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
page = p.chromium.launch().new_page()
page.goto("https://example.com/spa-product-page")
page.wait_for_selector(".price")
price = page.text_content(".price")
Why it works
Requests + BeautifulSoup (or Scrapy for larger jobs) skip browser startup and JS execution entirely, so they're an order of magnitude cheaper per page — appropriate when the data is already in the HTTP response. Checking for an underlying API before reaching for a browser avoids paying the rendering cost for data the site already serves as structured JSON. Playwright and Puppeteer are reserved for the case where content genuinely doesn't exist until the browser runs JavaScript against it.
Tips
- Scrapy adds a scheduler, retry logic, and pipelines on top of raw requests — worth it once you're managing dozens of concurrent scrape jobs, overkill for a handful of pages.
- Check a page's initial HTML (view-source, not the rendered DOM) before assuming you need a browser — a surprising number of "JS-heavy" sites server-render the content you actually need.
- Managed scraping platforms trade a per-request cost for not maintaining browser infrastructure, proxy rotation, and anti-bot workarounds yourself.
If you don't want to run and maintain your own Playwright infrastructure, WebCrawlerAPI renders JS-heavy pages and returns clean structured output through one API call.