Guides & Tutorials
Cheerio Web Scraping a Tutorial
A practical Cheerio walkthrough showing how to parse HTML in Node.js with familiar jQuery-style selectors, extract structured data, and scale scraping reliably.
Guides & Tutorials
A practical Cheerio walkthrough showing how to parse HTML in Node.js with familiar jQuery-style selectors, extract structured data, and scale scraping reliably.
Cheerio is a fast, lightweight library that brings jQuery-style syntax to server-side HTML parsing in Node.js. If you have ever written a selector like $('.title') in the browser, you already know most of Cheerio's API. It does not run JavaScript or render pages; it parses static HTML at speed, which makes it ideal when the data you want is already present in the page source.
This walkthrough covers installing Cheerio, loading HTML, selecting and extracting elements, looping through listings, and handling the realities of scraping many pages, including why proxies matter and how to compare them on value.
The base tutorial covers loading HTML, selecting, looping, and pagination. To go further, pull structured data straight from embedded JSON and metadata instead of brittle visual selectors, mine the network tab to fetch JSON APIs directly, run fetches concurrently behind a rate limit and rotating proxies, and pair Cheerio with a renderer only when content truly arrives via JavaScript. That mix is faster and far more resilient than scraping rendered text alone.
Cheerio takes a string of HTML and builds a traversable structure you query with CSS-style selectors. Because it skips the overhead of a full browser, it is dramatically lighter and faster than headless tools. The catch is that it only sees what arrives in the raw HTML response. If a site builds its content with client-side JavaScript after load, Cheerio sees the empty shell, not the final page.
So the rule of thumb is simple: if the data appears in view source, Cheerio is an excellent, efficient choice. If it only appears after scripts run, you need a rendering step first, then Cheerio can parse the result.
Cheerio parses HTML you supply, so pair it with a fetch library to retrieve pages. After installing, load the markup with cheerio.load, which returns a function conventionally named $.
npm install cheerio
const cheerio = require('cheerio');
async function getPage(url) {
const res = await fetch(url);
const body = await res.text();
return cheerio.load(body);
}With the loaded document, selection feels just like jQuery. You target elements by tag, class, id, or attribute, then read their text or attributes.
const $ = await getPage('https://example.com/products');
const firstTitle = $('.product .title').first().text().trim();
const link = $('a.next').attr('href');
console.log(firstTitle, link);
The key helpers are .text() for inner text, .attr(name) for attributes, .html() for inner markup, and .first() or .eq(i) to narrow a match set. Chaining these reads naturally and keeps extraction concise.
Most scrapes pull a list of records. Use .each() to iterate matched elements, scoping selectors to each item so fields stay aligned.
const products = [];
$('.product').each((i, el) => {
products.push({
title: $(el).find('.title').text().trim(),
price: $(el).find('.price').text().trim(),
url: $(el).find('a').attr('href'),
});
});
console.log(products);
Scoping with $(el).find(...) rather than a global selector is what keeps each record's fields matched to the right listing, which is the most common source of misaligned data for newcomers.
Real pages are inconsistent. Trim whitespace, default missing fields rather than letting them throw, and normalise values before storing. For multi-page results, read the next-page link, follow it, and repeat until it disappears.
let url = 'https://example.com/products?page=1';
const all = [];
while (url) {
const $ = await getPage(url);
$('.product').each((i, el) => all.push({
title: $(el).find('.title').text().trim() || null,
}));
const next = $('a.next').attr('href');
url = next ? new URL(next, url).href : null;
}Because Cheerio is so fast, your limiting factor when scraping many pages is the fetching layer. Sending a flood of requests from one IP invites rate limits and blocks. Rotating proxies spread requests across many addresses so your traffic resembles ordinary distributed visitors.
const res = await fetch(url, {
headers: { 'User-Agent': 'Mozilla/5.0 ...' },
// route through your proxy agent here
});
Combine proxies with good manners: stagger requests, set a realistic user agent, retry transient errors, and respect robots directives. When comparing providers, look at pool size, location coverage, success rate, and price as a whole rather than chasing the lowest number. For value-minded buyers, Cheapest Proxies is our featured value pick and a strong option to compare against the field.
A quick value-first shortlist — Cheapest Proxies leads as the featured pick. Qualitative labels only; confirm exact plans before buying.
| Provider | Best for | Profile | Value |
|---|---|---|---|
| Cheapest Proxies | Budget-conscious buyers comparing affordable proxies | Value Focused | Excellent value |
| Bright Data | Enterprises needing huge pools and compliance controls | Enterprise Focused | Premium |
| Oxylabs | Large-scale scraping and data APIs | Enterprise Focused | Premium |
| Smartproxy (Decodo) | Newcomers who want an easy dashboard | Beginner Friendly | Good |
| SOAX | Precise city and carrier targeting | Automation Friendly | Good |
The base walkthrough selects visible elements like titles and prices, but those selectors break whenever the layout shifts. Many sites embed the same information in machine-readable form that rarely changes. A JSON-LD script block can carry a product's full details in one place, and Open Graph meta tags expose title, image, and description in a consistent format across pages. Reading those with Cheerio gives you cleaner values with far fewer brittle selectors.
The pattern is simple: select the script or meta element, read its contents or attribute, and parse the JSON when present. Because this structured data is meant for machines, it is usually more stable across redesigns than the human-facing markup, making it the smarter first target when it exists.
Sometimes the best Cheerio scrape involves no HTML at all. Open the browser network tab and watch what loads after the page; listings frequently come from a JSON API the front end calls. Hitting that endpoint directly returns clean, structured data without parsing markup, which is faster and less fragile. Cheerio still earns its place for pages that genuinely ship their data in HTML, but checking for an underlying API first can save a lot of work.
A naive while-loop fetching one page at a time wastes Cheerio's speed waiting on the network. Run several fetches in parallel behind a fixed concurrency limit so you stay fast without flooding the target. Pair that with a small delay between requests and rotating proxies so traffic spreads across many addresses. The goal is throughput that looks like distributed visitors rather than a burst from one IP. For value-conscious projects, Cheapest Proxies is worth benchmarking against other providers on success rate, coverage, and price.
Cheerio cannot run JavaScript, so for truly dynamic pages you need a headless browser to render first. The efficient division of labor is to let the browser produce the final HTML, then pass that string to Cheerio, which parses and extracts far faster than doing all the work inside the browser context. Reserve the heavy renderer for the render step alone and keep your selection logic in lightweight Cheerio code.
Start on the smallest sensible tier and scale only what proves itself on your real targets.
Pick the proxy type the task needs first — it drives both success rate and cost more than the logo.
Check traffic limits, rotation rules and what happens on overage before you commit.
Our featured value pick, Cheapest Proxies, is a sensible starting point for affordable comparison.
Cheerio rarely fails on parsing; the fetch layer is where scrapes stall. That is exactly why comparing proxy providers on success rate, coverage, and price before you commit matters: the right infrastructure keeps a fast parser fed with clean responses, while the wrong one leaves your efficient code waiting on blocked requests.
Compare Proxy Zone weighs providers on value, fit and reliability using qualitative judgement — never invented prices, speeds or uptime figures. See our review methodology, or email info@compareproxyzone.com with a correction.
No, Cheerio only parses the raw HTML it is given, so for content rendered by client-side scripts you need a browser tool to render the page first, then parse it with Cheerio.
Cheerio just parses static HTML and is far lighter and faster, while a headless browser actually renders pages and runs JavaScript at a much higher resource cost.
Yes, Cheerio does not make HTTP requests; pair it with a fetch or request library to retrieve the HTML, then load that HTML into Cheerio.
You are likely using global selectors; scope each field with a per-item lookup so every record's fields stay tied to the correct listing.
Not for small jobs, but when you fetch many pages, rotating proxies help you avoid the rate limits and IP blocks that would otherwise interrupt your scraper.
Read the next-page link from the current page, resolve it to an absolute URL, fetch and parse it, and repeat the loop until no next link remains.
For affordable proxies across the main types, our featured value pick is Cheapest Proxies — a strong budget-friendly option worth considering. Check the exact plan before ordering.