Loading Documents

Before you can query a document, Cheerio has to parse it. Which method you reach for depends on where the markup comes from and whether you know its character encoding.

Tip

If you’re coming from jQuery, this step is new. jQuery operates on the one baked-in DOM of the page it runs on; with Cheerio you pass in the document yourself.

MethodInputUse it when
loadstringYou already have the markup as a string.
loadBufferBufferYou have raw bytes and the encoding is unknown.
stringStreamstream of decoded textYou’re streaming and already know the encoding.
decodeStreamstream of raw bytesYou’re streaming and the encoding is unknown.
fromURLURLYou want Cheerio to fetch the page for you.

The methods that accept bytes — loadBuffer and decodeStream — run the HTML encoding sniffing algorithm, so they will pick up a <meta charset> or a byte order mark. Prefer them whenever you can’t be sure the source is UTF-8.

Browser environments

Only load is available in the browser. loadBuffer, stringStream, decodeStream, and fromURL rely on Node.js APIs and are not included in the browser build.

load

load takes a string containing the document and returns a $ function you can use to traverse and manipulate it.

import * as cheerio from 'cheerio';

const $ = cheerio.load('<h1>Hello, world!</h1>');

console.log($('h1').text());
// Output: Hello, world!

Parsing fragments

Like a browser, load adds <html>, <head>, and <body> elements if they aren’t already present. Pass false as the third argument to parse the input as a fragment instead:

const $ = cheerio.load('<ul id="fruits">...</ul>', null, false);

$.html();
//=> '<ul id="fruits">...</ul>'

See Configuring Cheerio for details.

Learn more about the load method in the API documentation.

loadBuffer

loadBuffer works like load, but takes a Buffer instead of a string. Cheerio determines the encoding from the bytes themselves, which makes it the right choice for files and network responses whose encoding you don’t control.

import * as cheerio from 'cheerio';
import * as fs from 'node:fs';

// The file may be UTF-8, ISO-8859-1, … — Cheerio works it out.
const $ = cheerio.loadBuffer(fs.readFileSync('document.html'));

console.log($('title').text());

Learn more about the loadBuffer method in the API documentation.

stringStream

stringStream returns a writable stream that parses the document as it arrives. Use it when the encoding is already known, so the stream can be decoded to text before Cheerio sees it.

import * as cheerio from 'cheerio';
import * as fs from 'node:fs';

const writeStream = cheerio.stringStream({}, (err, $) => {
  if (err) {
    // Handle error
    return;
  }

  console.log($('title').text());
});

fs.createReadStream('document.html', { encoding: 'utf8' }).pipe(writeStream);

The first argument holds Cheerio’s options; the second is a callback that receives the finished document.

Learn more about the stringStream method in the API documentation.

decodeStream

decodeStream is the streaming counterpart to loadBuffer: it accepts raw bytes and runs the encoding sniffing algorithm before parsing. Reach for it when streaming a document of unknown encoding.

import * as cheerio from 'cheerio';
import * as fs from 'node:fs';

const writeStream = cheerio.decodeStream({}, (err, $) => {
  if (err) {
    // Handle error
    return;
  }

  console.log($('title').text());
});

// Note: no `encoding` option — the bytes are passed through as-is.
fs.createReadStream('document.html').pipe(writeStream);

Learn more about the decodeStream method in the API documentation.

fromURL

fromURL is the one loader that fetches for you. It is asynchronous, so await the result:

import * as cheerio from 'cheerio';

const $ = await cheerio.fromURL('https://example.com');

It does rather more than a bare fetch would, and the details are worth knowing:

  • Redirects are followed, up to five of them.
  • Non-2xx responses reject with an undici ResponseError carrying the status code, rather than handing you an error page to parse.
  • Non-markup responses reject with a RangeError. If the Content-Type is neither HTML nor XML, fromURL refuses rather than parsing a PDF as HTML.
  • XML mode is chosen for you from that same Content-Type, so an application/xml response is parsed as XML without your asking.
  • The encoding comes from the charset parameter of the Content-Type when present, and from sniffing the bytes otherwise.
  • baseURI is set to the final URL — after redirects. That is what lets prop('href') and extract hand you absolute links.

Customizing the request

Pass requestOptions to control the request. These go to undici’s stream method:

const $ = await cheerio.fromURL('https://example.com', {
  requestOptions: {
    method: 'GET',
    headers: {
      'user-agent': 'my-scraper/1.0 (+https://example.com/bot)',
    },
  },
});

requestOptions

Two things to watch for:

  • method is not defaulted. Supplying requestOptions without it fails with method must be a string, so always include it.
  • headers is all-or-nothing. Omit it and you keep Cheerio’s default Accept header; supply it and yours replaces that default outright, rather than being added to it.

Learn more about the fromURL method in the API documentation, and see Security before pointing it at a URL that came from a user.