In This Article

Back to blog

Web Scraping with Cheerio and Node.js: A Beginner-Friendly Guide

Tutorials

Nerijus Kriaučiūnas

Last updated - ‐ 8 min read

Key Takeaways

  • Cheerio web scraping is great for fast projects that don’t need JavaScript.

  • Always handle errors properly, respect robots.txt, and space out your HTTP requests.

  • Pair Cheerio with Axios, save your results to a JSON file, and add proxies once you scale up.

If you’re thinking about getting into web scraping, that’s a good call on your side. It’s one of the best ways to gather data from web pages without copy-pasting everything by hand. And with the help of Cheerio in Node.js, you can start small and learn quickly without many headaches.

In this guide, we will walk you through everything you need to know: setting up your tool, building a web scraper to scrape data, and how to handle some common errors.

Prerequisites

Before you scrape data from live pages and write your extraction scripts, you need a few fundamentals in place. Setup takes only a few minutes if you already understand how HTML structures content on web pages.

  • Node.js installed on your computer.
  • A plain text editor or an integrated development environment (IDE).
  • Basic familiarity with JavaScript syntax and standard document object models.

What Is Cheerio in Node.js?

The Cheerio library is a lightweight library for parsing HTML and XML in Node.js. It’s essentially jQuery without the browser – you get the same familiar syntax for selecting elements and changing markup, minus the rendering engine. It’s most commonly used server-side, and it helps you move through the DOM (Document Object Model) of various web pages without needing a browser.

People love it because it’s fast and doesn’t rely on visual rendering. Cheerio gets the job done faster than most web scraping libraries if you don’t need to execute JavaScript. It was built as a server-side implementation of core jQuery, which is exactly why it works so well for web scraping, as you get jQuery’s selector syntax without the browser overhead.

Cheerio is at its best when you only need static content and not interactive or dynamic data like drop-downs or pop-ups. You should use Cheerio when you need speed and don’t care about animations or dynamic scripts.

However, if you do need to execute JavaScript, scrape from pages that change after each load, or are automating tests in a browser environment, Puppeteer could be a better choice. We’ll provide a brief comparison between the two later in the article.

The best part is that Cheerio is a completely open-source NPM package, and anyone can contribute to it. Also, it’s totally free to use under the MIT license.

Ready to get started?
Register now

Setting Up Node.js and Cheerio

Before you do anything else, make sure Node.js is installed. Then create a project folder, initialize it, and install both packages:

mkdir web-scraper && cd web-scraper
npm init -y
npm install cheerio axios

You need Axios because it’s a promise-based HTTP client that we will use to make HTTP requests and handle any raw HTML or JSON response. Here’s a simple structure to keep things clean:

/web-scraper
│
├── index.js
├── package.json
└── /data

Keep your entire web scraper logic in index.js for now. You can organize later when your projects grow.

Cheerio Basics: Selecting and Managing HTML

Before you scrape websites live, you need to know how Cheerio handles basic HTML selections. Master these core methods for selecting elements, and you will be able to target specific data on any page.

You can practice by loading a hardcoded HTML string directly into Cheerio. This lets you see exactly how extracting data works without making network requests.

const cheerio = require('cheerio');

const htmlData = `
<div id="wrapper">
    <h1 class="title">Main Heading</h1>
    <ul class="items">
        <li data-id="1">First item</li>
        <li data-id="2">Second item</li>
    </ul>
</div>
`;

const $ = cheerio.load(htmlData);

const titleText = $('.title').text();
console.log(titleText); 

const listHtml = $('.items').html();
console.log(listHtml); 

$('li').each((index, element) => {
    const id = $(element).attr('data-id');
    const text = $(element).text();
    console.log(`Item ${id}: ${text}`);
});

const parentTag = $('.title').parent().attr('id');
console.log(parentTag); 

These commands give you all that you need to start getting data points with minimal code.

How To Find The Right Selectors

Before writing any scraper code, inspect the live page to see how the markup is structured. Open Chrome Developer Tools by right-clicking an element and selecting Inspect.

It highlights the exact classes, IDs, and every CSS selector tied to the data that you want. If you go for highly specific CSS selectors, your scraper will most likely break since websites update their layouts and class names quite frequently. To be on the safe side of that, write fallback rules that target broader HTML patterns if your primary selectors fail.

Building Your First Web Scraper

Now, let’s build a basic scraper using an async function. To make it easier to understand, let’s create a script that will grab news headlines from a public site.

#!/usr/bin/env node

const axios = require('axios');
const cheerio = require('cheerio');

const URL = 'https://www.theguardian.com/europe';
const selectors = [
  'h3.card-headline span.show-underline',         // main cards
  'h3.card-sublink-headline span.show-underline', // sub-links under cards
  'a.js-headline-text'                            // standard News list items
];

async function fetchHeadlinesVerbose() {
  try {
    // 1) Fetch page
    console.log('>> Fetching:', URL);
    const { data: html } = await axios.get(URL, {
      headers: { 'User-Agent': 'Mozilla/5.0' }
    });
    console.log(`>> Loaded HTML (length ${html.length} chars)`);
    console.log(html.slice(0, 200).replace(/\n/g, ' ') + '…\n');

    // 2) Load into Cheerio
    const $ = cheerio.load(html);

    const allFound = new Set();

    // 3) Try each selector
    for (const sel of selectors) {
      const elems = $(sel);
      console.log(`>> Selector "${sel}" matched ${elems.length} elements`);
      elems.slice(0, 5).each((i, el) => {
        const txt = $(el).text().trim();
        console.log(`   [${i+1}] "${txt}"`);
        if (txt) allFound.add(txt);
      });
    }

    // 4) Fallback if nothing
    if (allFound.size === 0) {
      console.warn('⚠️ No headlines found with the specific selectors—falling back to any /2026/ links');
      const fallback = $('a[href*="/2026/"]');
      console.log(`>> Fallback selector matched ${fallback.length} links`);
      fallback.slice(0, 5).each((i, el) => {
        const txt = $(el).text().trim();
        console.log(`   [${i+1}] "${txt}"`);
        if (txt) allFound.add(txt);
      });
    }

    // 5) Final output
    const list = Array.from(allFound);
    console.log(`\n>> Total unique headlines collected: ${list.length}\n`);
    list.forEach((h, i) => console.log(`${i+1}. ${h}`));

  } catch (err) {
    console.error('❌ Error fetching/parsing page:', err.message);
  }
}

fetchHeadlinesVerbose();

This function pulls the HTML from your target web pages, loads it into the Cheerio object, and finds headline tags. You can tailor this script to scrape data and pull any other static data points from websites that you need. Just keep in mind that you’ll need to adjust the script accordingly.

Cheerio web scraping is light, fast, and simple. There’s no need to mess with page loads or visual rendering.

Saving Scraped Data to a File

Console logging works for testing, but real projects require saved data. Use the built-in fs module to save your arrays as a JSON object directly into a JSON file for easy reading later.

const fs = require('fs');

const scrapedData = [
    { id: 1, title: 'First Headline' },
    { id: 2, title: 'Second Headline' }
];

fs.writeFile('data.json', JSON.stringify(scrapedData, null, 2), (err) => {
    if (err) throw err;
    console.log('Data successfully saved to data.json');
});

If you need to share data with non-technical teams, write your output to a CSV file so they can open it in a spreadsheet.

Using Proxies With Axios to Avoid Blocks

Target servers often detect and block rapid automated requests, but that’s not a big problem. You can stay within these limits by spreading traffic across multiple web scraping proxies instead of sending everything from a single one.

Since you’re using Axios, you can pass proxy credentials directly inside your request config.

const axios = require('axios');

const proxyConfig = {
    protocol: 'http',
    host: 'geo.iproyal.com',
    port: 12321,
    auth: {
        username: 'your_username',
        password: 'your_password'
    }
};

axios.get('https://example.com', { proxy: proxyConfig })
    .then(response => {
        console.log('Successfully connected through proxy');
    })
    .catch(error => {
        console.log('Connection failed:', error.message);
    });

For sites with stricter rate limiting, rotating residential proxies — or even mobile proxies — work best, since their IP addresses come from real consumer connections and requests are distributed across a large pool. For more basic tasks, or when you're just automating tests, datacenter proxies work just fine and are considerably faster.

Error Handling & Best Practices

Sometimes code breaks, and it happens more often than you may think. You should always use try/catch when making HTTP requests. Also, check for missing elements. Not all web pages have what you’re looking for.

Here are some more best practices for you:

  • Respect robots.txt. If the site doesn’t allow web scraping, you should respect it.
  • Set delays. Don’t hit a target web server with hundreds of requests per second.
  • Use headers. Set a descriptive user-agent so the target web server can identify your requests properly.
  • Handle rate limits. Implement retries with exponential backoff, so your script waits slightly longer after each failed connection attempt.
  • Use a proxy. If you’d like to minimize your chances of getting blocked, you may want to try rotating proxies .
  • Handle missing elements. Write logic that moves forward smoothly when a specific piece of information does not exist on the target page.
  • Validate extracted data before storage. It will ensure you pulled complete strings rather than empty spaces or undefined errors.

Cheerio vs Puppeteer: Which Should You Use?

If you’re trying to decide between scraping with Puppeteer or Cheerio , here’s a quick comparison to help you decide:

Feature Cheerio Puppeteer
Speed Fast Slower
Loads JavaScript No Yes
Good for static HTML Yes Yes
Needs browser No Yes
Easy to learn Very easy A bit more complex

In short, if you don’t need any interactivity, Cheerio web scraping is the better pick. You’ll avoid overhead and finish your tasks faster.

The speed difference is significant in practice. Cheerio typically completes a scrape in around 500 milliseconds, while Puppeteer takes roughly 4,000 milliseconds for the same job, as it has to launch a headless browser, load assets, and render the page before it can read anything.

Conclusion

If you’re new to web scraping, the Cheerio library makes it easy to start your web data extraction journey. It has a simple syntax and fast HTML parsing, which makes it great for scraping websites that don't rely on dynamic scripts.

Pair it with a promise-based HTTP client like Axios, and you’ve got a solid toolset for scraping static web pages.

FAQ

Can Cheerio scrape JavaScript-rendered pages?

No, Cheerio only parses static HTML. It cannot execute JavaScript or render dynamic content that loads after the initial page request.

Is Cheerio faster than Puppeteer?

Yes. Cheerio is much faster because it only parses text. It skips the heavy lifting of launching a headless browser, loading images, and rendering CSS layouts.

Do I need proxies to scrape with Cheerio?

You can test scripts locally, but larger projects require proxies. Websites will quickly block your IP address if you send too many automated requests at once.

What is the difference between Cheerio and Axios?

Axios fetches the HTML source code from the target website. Cheerio parses that HTML so you can extract specific data points from it.

Is web scraping with Cheerio legal?

Scraping publicly available data is generally legal. Just ensure you comply with local privacy laws and avoid extracting protected personal information.

How do I handle pagination when scraping with Cheerio?

Use Cheerio to extract the href attribute of the next page button. Pass that URL back to your request library in a loop until no more web pages exist.

Create Account
Share on
Article by IPRoyal
Meet our writers
Data News in Your Inbox

No spam whatsoever, just pure data gathering news, trending topics and useful links. Unsubscribe anytime.

No spam. Unsubscribe anytime.

Related articles