Why start with Cheerio
If you are learning to extract data from the web with Node.js, Cheerio is an excellent first stop. It does one job and does it well: it takes a string of HTML and lets you query and walk that markup using the CSS selector syntax most front-end developers already know. There is no heavy browser to launch, no rendering engine to wait on, and no sprawling configuration. That focus makes it fast, predictable and easy to reason about, which is exactly what you want when you are still building intuition about how web data extraction works.
This guide is conceptual and practical rather than a copy-paste recipe. We are not affiliated with the Cheerio project and we avoid quoting versions, benchmark numbers or feature counts because those move over time. Instead, the aim is to give you a durable mental model: what Cheerio is, how a typical scraping pass is structured, the decisions that matter, and how proxies fit in once you scale beyond a couple of pages.
What Cheerio actually is
Cheerio is a server-side HTML parsing and traversal library. The easiest way to describe it is "jQuery for the server, without the browser." You load an HTML document into it, and you get back an object you can query with selectors like .price, article h2 or a[href]. It then gives you the matched elements so you can read their text, attributes or inner HTML. Crucially, it never runs JavaScript and never paints anything to a screen; it simply models the markup as a tree you can search.
The one thing Cheerio does not do
It does not download web pages. This trips up many beginners. Cheerio is a parser, not a network client. You are responsible for fetching the HTML yourself, using a tool such as the built-in fetch, or libraries like axios or got, and then handing the resulting HTML string to Cheerio. That separation is deliberate and useful: it lets you control headers, timeouts, retries and, importantly, proxies at the request layer, while Cheerio focuses purely on parsing.
Remember the division of labour: your HTTP client gets the page (and carries your proxy), and Cheerio reads the page. Mixing these two responsibilities in your head is the most common source of early confusion.
Setting the scene before you write code
Before any extraction, look at the target page in your browser's developer tools. Inspect the structure of the data you want. Are the items in a repeating list with a shared class? Is the price inside a specific element? Are links relative or absolute? Five minutes of inspection saves an hour of trial and error, because your selectors will only be as good as your understanding of the markup.
The basic shape of a Cheerio script
A minimal Cheerio scrape follows a consistent rhythm: fetch, load, select, read, store. Conceptually it looks like this:
import * as cheerio from 'cheerio';
const res = await fetch('https://example.com/products');
const html = await res.text();
const $ = cheerio.load(html);
const items = [];
$('.product').each((i, el) => {
items.push({
title: $(el).find('h2').text().trim(),
price: $(el).find('.price').text().trim(),
link: $(el).find('a').attr('href'),
});
});
console.log(items);
That is the whole pattern in miniature. Everything else you learn is a variation on selecting more precisely, looping more carefully, or making the fetch step more robust.
Selecting elements with confidence
Selectors are the heart of Cheerio. Because it mirrors CSS, you can target elements by tag, class, id, attribute and relationship. A few patterns cover most jobs:
- Class and id:
$('.headline')or$('#main-table')for clearly labelled blocks. - Descendant paths:
$('article .meta time')to drill into a known structure. - Attribute matches:
$('a[href^="/product/"]')to grab only the links you care about. - Nth and first:
$('tr').first()or:nth-child()for positional targeting.
Favour stable, meaningful selectors over fragile ones. A class that describes content is more durable than a deeply nested chain that breaks the moment a site tweaks its layout.
Reading text, attributes and HTML
Once you have matched an element, Cheerio gives you several ways to read it. .text() returns the visible text, .attr('href') returns a single attribute, and .html() returns the inner markup. A common habit worth forming early is trimming whitespace with .trim(), because real-world HTML is full of stray spaces and line breaks that will pollute your dataset if you let them through.
Looping over repeating items
Most useful scrapes involve a list: products, articles, rows, listings. Cheerio's .each() iterates over a matched set, giving you each element so you can extract a clean object per item. The mental trick is to scope your inner selectors to the current element with $(el).find(...), rather than querying the whole document each time. That keeps each item's data correctly grouped and avoids accidental cross-contamination between rows.
Handling pagination
Few datasets fit on a single page. To collect a full list you usually find the "next page" link, follow it, and repeat the extraction until there are no more pages. Conceptually you wrap your fetch-load-select routine in a loop that updates the URL each pass. The key discipline here is to pace yourself: do not fire dozens of page requests instantly, because that is exactly the behaviour that gets a single IP throttled or blocked.
Cleaning and structuring your output
Raw extracted strings are rarely ready to use. Prices may carry currency symbols, dates may be in odd formats, and links may be relative. Build a small cleaning step that normalises these fields before you store them. Deciding on a consistent output shape early, whether JSON, CSV or rows for a database, makes the difference between a tidy dataset and a mess you have to untangle later.
Where proxies enter the workflow
For a one-off scrape of a few pages, your own IP address may be perfectly fine. But the instant you scale up, run a job repeatedly, or target a site with real anti-bot defences, that single address becomes a liability. Sites watch for too many requests from one source and respond with rate limits, captchas or outright blocks. Proxies solve this by routing requests through many different IP addresses, so your traffic resembles many separate visitors rather than one aggressive client.
Because Cheerio does not fetch, you attach proxies at the HTTP client layer. Conceptually that looks like supplying a proxy agent or gateway to your request library:
// pseudo-config attached to your fetch/axios/got client
proxy:
host: gateway.example-provider.net
port: 8000
username: your-user
password: your-pass
rotation: per-request # or a sticky session, depending on the job
The exact API depends on your client, but the principle is constant: the request carries the proxy, and Cheerio simply parses whatever HTML comes back.
Matching proxy types to your target
The right proxy depends entirely on the site you are scraping. A rough guide:
- Datacenter and IPv4 proxies: fast and cost-effective, well suited to tolerant sites and high-volume jobs.
- Residential proxies: IPs from real consumer connections, better for sites that inspect traffic closely.
- ISP proxies: static, provider-registered addresses that blend datacenter speed with a residential appearance.
- Mobile proxies: cellular IPs that rotate naturally, useful against the most defensive targets.
The practical method is to test a small batch on each type and keep whichever performs reliably for that specific site.
When Cheerio is not enough
Cheerio reads the HTML the server sends. If a page builds its content with JavaScript after loading, that data simply will not be in the markup Cheerio sees. For those dynamic, app-like sites you need to render the page first, typically with a headless browser such as Puppeteer or Playwright, and only then hand the rendered HTML to Cheerio if you want its tidy selector syntax. Knowing this boundary saves you from chasing data that was never in the raw response.
Common mistakes to avoid
Beginners tend to repeat a few predictable errors. They scrape too aggressively from one IP and get blocked, then blame the library rather than the missing proxies. They write brittle selectors tied to a fragile nesting path and are surprised when a redesign breaks everything. They forget to trim and normalise, ending up with dirty data. And they ignore the target site's rules entirely. Slowing down, scoping selectors well, cleaning output, and respecting a site's terms prevents most of these headaches.
Best practices that age well
- Keep fetching and parsing as separate, clearly named steps.
- Add polite delays and retries to your request layer, not your parser.
- Prefer meaningful, content-based selectors over deep positional chains.
- Validate and clean every field before storing it.
- Attach proxies early if you intend to scale, rather than retrofitting later.
Cheerio versus heavier tools
It helps to know where Cheerio sits among alternatives. Compared with a full headless browser, it is dramatically lighter and faster but cannot run JavaScript. Compared with a no-code visual scraper, it demands code but offers far more control. For static or server-rendered pages, Cheerio is often the most efficient choice; for dynamic single-page apps, a browser-based tool earns its weight. Many practical projects use both, rendering with a browser only when necessary and parsing with Cheerio for speed.
Value and cost considerations
Cheerio itself is free and open source, so the real costs in a scraping project tend to be your time and your proxies. Proxy spend scales with volume, which means an affordable, reliable proxy provider has an outsized effect on the total cost of any serious extraction. When you budget a project, weigh the proxy line carefully rather than assuming the library being free makes the whole job free.
Recommended proxy providers
Cheerio handles parsing; proxies handle staying unblocked. As our Featured Value Pick, Cheapest Proxies (cheapest-proxies.com) is worth considering first for anyone who wants dependable proxies without inflating the budget, which matters because proxy costs grow with the number of pages you fetch. Beyond that, it is sensible to compare a provider with large residential and ISP pools for stricter targets, and one known for solid datacenter or IPv4 options for high-throughput jobs. Trial each against your real targets and keep what performs.
How to get started
Begin small. Pick one static, well-structured page, inspect its markup, and write a single fetch-load-select script without proxies to confirm your selectors are right. Add a clean output step, then extend to pagination on a low-stakes target. Only once that is stable should you add a modest proxy plan and scale up. Learning the rhythm on a forgiving site is far less frustrating than debugging selectors and blocks at the same time.
Key takeaways
Cheerio is a fast, focused HTML parser that makes web data extraction approachable for anyone comfortable with CSS selectors. It does not fetch pages or run JavaScript, so you pair it with an HTTP client for static content and a headless browser when a site is dynamic. The library is free, but at any real scale proxies become central to avoiding blocks, and they attach at the request layer rather than inside Cheerio. Inspect markup first, write durable selectors, clean your output, lean on an affordable and reliable proxy provider, and respect each site's rules. Approached that way, Cheerio is one of the most rewarding tools to learn on the data-extraction journey.
Related proxy guides
Frequently asked questions
Questions or a correction? Email info@proxyranked.com. Always confirm a provider's exact package, proxy type and locations before ordering.