← All articles

Tutorials

List Crawling in Python: How to Crawl Listing Pages at Scale

Alex R. · July 20, 2026 · 8 min read


Most real scraping jobs are not "grab one page." They are "collect every product in a category," "every job in a board," "every listing in a directory." That is list crawling: systematically walking a set of listing pages to gather items, then optionally following each to its detail page. Master this pattern and you can scrape almost any structured site. This guide shows the two-phase approach in Python, how to handle every pagination style, and how to run it at scale.

What Is List Crawling?

List crawling is different from scraping a single page. A listing page (a category, search result, or index) shows many items in a repeating structure, usually across multiple pages. List crawling means:

  1. Crawl the listing pages — follow pagination to collect the link to every item.
  2. Visit each item — fetch each detail page and extract its full data.

Splitting the job into these two phases keeps it reliable: you get a complete, deduplicated list of URLs first, then process them independently. It is the same idea behind frameworks like Scrapy, and it pairs naturally with the fundamentals in building a web scraper in Python. For the distinction between crawling and scraping, see web crawling vs web scraping.

Phase 1: Crawl the Listing Pages

Walk through the paginated list and collect every item link. Using the practice site books.toscrape.com as a safe example, and routing through a residential proxy:

import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup

proxy = "http://USERNAME:[email protected]:12321"
proxies = {"http": proxy, "https": proxy}
BASE = "https://books.toscrape.com/catalogue/"

def collect_links(start="page-1.html"):
    links, page = [], start
    while page:
        soup = BeautifulSoup(requests.get(BASE + page, proxies=proxies, timeout=20).text, "html.parser")
        for a in soup.select("article.product_pod h3 a"):
            links.append(urljoin(BASE, a["href"]))
        nxt = soup.select_one("li.next a")           # follow the "next" link
        page = nxt["href"] if nxt else None
    return links

Notice the loop follows the "next" link until there is not one — a robust way to reach the last page without guessing how many pages exist.

Phase 2: Visit Each Item

With the full link list in hand, fetch each detail page and pull its fields:

def scrape_item(url):
    soup = BeautifulSoup(requests.get(url, proxies=proxies, timeout=20).text, "html.parser")
    return {
        "url": url,
        "title": soup.select_one("h1").get_text(strip=True),
        "price": soup.select_one(".price_color").get_text(strip=True),
        "availability": soup.select_one(".availability").get_text(strip=True),
    }

links = collect_links()
data = [scrape_item(u) for u in links]
print(len(data), "items")

Handling Every Pagination Style

Real sites paginate in different ways — identify which one you are dealing with:

Running It at Scale

Crawling thousands of pages against one site quickly triggers rate limits and bans. Three things keep a large crawl alive:

Save the collected items to JSON to preserve structure, or flatten to CSV for analysis (see JSON vs CSV).

Common Pitfalls

Frequently Asked Questions

What is list crawling?

List crawling is the pattern of walking through a site's paginated listing pages (a category, search, or index) to collect the link to every item, then visiting each item's detail page to extract its data. It is the two-phase backbone of most large scraping projects.

How do I handle pagination in Python?

The most robust method is to follow the "next" link on each listing page until there is not one. Alternatively, increment a page or offset parameter until a page returns no items. For JavaScript "load more" or infinite scroll, call the underlying JSON API the page uses, or render it with a headless browser like Playwright.

Do I need proxies for list crawling?

For any sizeable crawl, yes. Requesting hundreds or thousands of pages from one site quickly triggers rate limits and IP bans. Rotating residential proxies send each request from a different real IP, so the crawl can finish without a single address getting blocked.

How do I speed up a large crawl?

Fetch detail pages concurrently with async or a thread pool, cap the concurrency so you stay polite, deduplicate URLs, retry failures with backoff, and cache fetched pages so a re-run does not repeat work. Rotating proxies let you raise concurrency without tripping rate limits.

Conclusion

List crawling is the pattern that turns a one-page scraper into a tool that can harvest an entire catalog: collect every item link by following pagination, then visit each detail page. Identify the pagination style, split the job into two phases, and route it all through rotating residential proxies so a big crawl actually finishes.

Crawl at scale without bans: SpyderProxy residential proxies from $2.75/GB — rotating, ethically sourced, across 195+ countries.

Ready to collect data without getting blocked?

Start now ↗