Web Scraping with Python: requests + BeautifulSoup
Data lives in web pages. Fetch, parse and extract it cleanly — and do it politely.
In this guide
Most of the data you need isn't in a tidy CSV — it's in a web page. Scraping bridges that gap. We use it constantly for datasets, research and monitoring. Here's the clean, responsible way.
Fetch a page
pip install requests beautifulsoup4 lxmlimport requests
from bs4 import BeautifulSoup
resp = requests.get(
"https://books.toscrape.com/",
headers={"User-Agent": "Mozilla/5.0 (compatible; tutorial/1.0)"},
)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "lxml")Find elements
# CSS selectors are usually the cleanest
titles = [h3.a["title"] for h3 in soup.select("h3")]
prices = [p.text.strip() for p in soup.select(".price_color")]
for t, p in zip(titles, prices):
print(t, "—", p)soup.select() accepts any CSS selector; .find() and .find_all() are the older API. Prefer selectors.
Extract attributes and text
link = soup.select_one("h3 a")
href = link["href"] # attribute access
text = link.get_text(strip=True)Handle pagination
import time
def scrape_page(url):
r = requests.get(url, headers={"User-Agent": "tutorial/1.0"})
return BeautifulSoup(r.text, "lxml")
page = scrape_page("https://books.toscrape.com/")
while True:
nxt = page.select_one("li.next a")
if not nxt:
break
time.sleep(1) # be polite
page = scrape_page("https://books.toscrape.com/" + nxt["href"])Etiquette matters. Respect robots.txt, throttle yourself, and don't hammer a small site. Scraping responsibly is the difference between a useful tool and a nuisance.
When scraping gets hard
- Dynamic pages rendered by JS → use Playwright or a headless browser.
- Login walls → use a session and persist cookies.
- Rate limits → rotate proxies and back off exponentially.
Master these basics and you can turn any public page into structured data.
More from the lab
Build a REST API with FastAPI and SQLite
From zero to a documented, validated CRUD API in one file — the fastest Python back end there is.
DevOpsDocker for Beginners: Containers Explained
What a container actually is, how a Dockerfile works, and how to ship an app that runs everywhere.
DevOpsA Clean Git Branching Strategy for Teams
Keep main green and releases boring with a lightweight trunk-based Git workflow.
Want us to build this for you?
We turn tutorials like these into production systems every day. Tell us what you need.
Start a project →