What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use Cheerio’s normal CSS selector entry point, $(), with an attribute selector such as [data-kind="note"]. Presence selectors ([attr]), exact matches ([attr="value"]), and prefix, suffix, or substring operators let you find the elements you need; then use attr(), text(), each(), map(), find(), and filter() to extract or narrow results.
Basic attribute selection
Cheerio uses CSS selectors—the same selector syntax used in a stylesheet or with document.querySelectorAll. Load the HTML, pass a selector to $(), and inspect the returned selection.
import * as cheerio from 'cheerio';
const html = `
<article>
<a data-kind="note" href="/one">First</a>
<a data-kind="link" href="https://example.com/two">Second</a>
<a href="/three">Third</a>
</article>
`;
const $ = cheerio.load(html);
const notes = $('[data-kind="note"]');
console.log(notes.length); // 1
console.log(notes.attr('href')); // /one
console.log(notes.text()); // First
The selector is evaluated against the HTML supplied to cheerio.load(); Cheerio does not automatically open a URL or execute the page’s JavaScript.
Attribute selector patterns you can use
Test whether an attribute exists
[data-kind] matches every element that has a data-kind attribute, regardless of its value. This is the safest first diagnostic when an exact selector returns zero results.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
const marked = $('[data-kind]');
console.log(marked.length);
Match an exact value
[data-kind="note"] requires both the attribute and the exact value. Add a tag name when you want to exclude other element types: a[data-kind="note"].
const noteLinks = $('a[data-kind="note"]');
Quote values containing punctuation, spaces, or other characters that could be interpreted as selector syntax. Quoting also makes the intended match unambiguous.
Match prefixes, suffixes, and substrings
[href^="https://"]matches values beginning withhttps://.[href$=".pdf"]matches values ending with.pdf.[href*="example"]matches values containingexample.
const secureLinks = $('a[href^="https://"]');
const pdfLinks = $('a[href$=".pdf"]');
const exampleLinks = $('a[href*="example"]');
Match tokens and language prefixes
[class~="featured"] treats the value as a space-separated token list, so it matches an element whose class list contains featured but not one whose class is featured-card. [lang|="en"] matches en and values beginning with en-, such as en-US.
Namespaced attributes
Escape the colon when selecting a namespaced attribute:
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →const main = $('[xml\:id="main"]');
Combine attributes with other CSS selectors
Attribute selectors can be combined with tags, classes, relationships, and comma-separated alternatives.
// Descendants of article
const notesInArticles = $('article a[data-kind="note"]');
// Direct children only
const navLinks = $('nav > a[data-kind="link"]');
// Either heading level
const titles = $('h1[data-role="title"], h2[data-role="title"]');
A descendant space allows any depth; > restricts the match to direct children. You can add classes or IDs in the usual way, for example div.card[data-state="open"].
Rank #2
Narrow an existing selection with traversal methods
When you already have a broad selection, traversal methods make the intent clearer than repeating a long selector.
const articles = $('article');
const notes = articles.find('[data-kind="note"]');
const featured = notes.filter('.featured');
const first = notes.first();
const last = notes.last();
const third = notes.eq(2);
find() searches within the current selection and returns a new selection. filter() keeps only elements matching the supplied selector. first(), last(), and eq(index) select a particular item. Cheerio’s selector engine also supports jQuery-style positional forms such as :first, :last, and :eq(n); these are Cheerio extensions rather than standard browser CSS.
Read attributes and text from matches
Read one value
attr('href') reads the attribute from the first element in the selection. It returns undefined when no matching element or attribute exists.
const link = $('a[data-kind="note"]');
const href = link.attr('href');
const label = link.text();
console.log({ href, label });
Extract every match with each()
Use each() when you want to process every element and can perform work inside the callback.
const rows = [];
$('a[data-kind]').each((index, element) => {
rows.push({
index,
kind: $(element).attr('data-kind'),
href: $(element).attr('href'),
text: $(element).text().trim()
});
});
console.log(rows);
Build an array with map()
map() is convenient when each element becomes one value. Call get() to convert the Cheerio collection into a normal JavaScript array.
const links = $('a[data-kind]').map((index, element) => ({
kind: $(element).attr('data-kind'),
href: $(element).attr('href'),
text: $(element).text().trim()
})).get();
Use prop() when you need a property supported by Cheerio rather than the literal attribute value. For ordinary HTML attributes such as href, attr() is usually the appropriate API.
Recommended Free Tools
Rank #3
Find several attribute conditions in one pass
Selectors can express multiple requirements. For example, this finds only links inside a navigation element that have an HTTPS URL and a specific data role:
const externalNavLinks = $('nav a[data-role="external"][href^="https://"]');
Use a comma-separated selector when the alternatives are independent:
const headings = $('[data-role="title"], [data-role="subtitle"]');
For a broad result followed by conditional logic, select first and filter in JavaScript. This is useful when the rule is not expressible in CSS or requires parsing the value.
const numbered = $('[data-id]').filter((index, element) => {
const id = $(element).attr('data-id');
return id ? /^item-d+$/.test(id) : false;
});
Safely build selectors from input
Do not concatenate untrusted or arbitrary values into a selector without escaping selector-special characters. Periods, colons, spaces, quotation marks, brackets, and backslashes can change the meaning of the selector or make it invalid. Prefer a selector-escaping utility appropriate to your application, or avoid interpolation by selecting [data-key] and comparing the attribute value in JavaScript.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesconst wanted = 'note:primary';
const matches = $('[data-kind]').filter((index, element) =>
$(element).attr('data-kind') === wanted
);
This comparison approach avoids selector parsing entirely. If you do interpolate a value, escape it according to the selector engine’s rules before constructing the selector.
Why an attribute selector returns nothing
Verify the input HTML
The most common problem is that the string passed to cheerio.load() is not the HTML you think it is. Log a short fragment, the document title, or the total element count before debugging the selector.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
const $ = cheerio.load(html);
console.log($.html().slice(0, 500));
console.log('all elements:', $('*').length);
console.log('attribute elements:', $('[data-kind]').length);
Reduce the selector step by step
- Start with the attribute-presence test, such as
[data-kind]. - Add the tag name:
a[data-kind]. - Add the exact value:
a[data-kind="note"]. - Add relationship constraints such as
article a[data-kind="note"].
The first step that changes the count identifies the part of the selector that needs correction.
Check spelling, case, and value formatting
HTML attribute names are generally case-insensitive, but values are data-dependent. A value of Note does not necessarily equal note. Watch for whitespace, URL encoding, missing prefixes, and attributes whose value is generated differently than expected.
Free tools Windows power users keep installed
One-click scans. No signup required.
Account for client-side rendering
React, Vue, and other frameworks may create nodes only after browser JavaScript runs. Cheerio sees the response HTML you provide; it does not run that application code. Obtain server-rendered HTML, call the underlying data API, or use a browser-capable capture step before passing the resulting HTML to Cheerio.
Check the attribute type
An element may expose a browser property without carrying the corresponding source attribute. Inspect the raw HTML and choose attr() for source attributes or prop() for supported properties.
A reusable extraction function
The following function returns normalized records and handles missing attributes without throwing:
import * as cheerio from 'cheerio';
export function findByAttribute(html, attribute, expectedValue) {
const $ = cheerio.load(html);
const selector = `[${attribute}]`;
return $(selector).filter((index, element) => {
if (expectedValue === undefined) return true;
return $(element).attr(attribute) === expectedValue;
}).map((index, element) => ({
tag: element.name,
value: $(element).attr(attribute),
text: $(element).text().trim()
})).get();
}
console.log(findByAttribute(html, 'data-kind', 'note'));
If attribute itself can come from untrusted input, validate it against an allowlist of expected attribute names before constructing the presence selector.
Best Value
Performance and reliability considerations
- Use the narrowest selector that expresses your requirement; it reduces traversal and makes accidental matches less likely.
- For repeated extraction, select once and iterate rather than reparsing the same HTML.
- Keep network fetching separate from parsing so you can log response status, content type, and the exact HTML given to Cheerio.
- Expect malformed or partial HTML from failed requests and verify that the response is actually HTML rather than a bot-check page, JSON error, or login form.
- When pages are large, extract the required fields during one pass and discard the document when finished instead of retaining many Cheerio selections.
Or skip the browser setup
If the page requires a real browser to render content or to clear consent UI before you obtain HTML or an image, ScreenshotNeo provides a one-request screenshot API. It accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server supplies take_screenshot, get_page_info, and capture_pdf tools to Claude, Cursor, and other MCP clients.
See the ScreenshotNeo documentation for parameter details. A direct cURL request is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same call in Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Every plan includes full-page capture, element selection, custom CSS and JavaScript, waits, request blocking, cookies and headers, device and viewport controls, PDFs, signed links, asynchronous jobs, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification. The service also accepts parameter names used by other screenshot APIs.
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free. Create a free ScreenshotNeo account to start without a card.
Frequently Asked Questions
Does Cheerio execute JavaScript from the page?
No. Cheerio parses the HTML string you provide. For client-rendered nodes, obtain server-rendered HTML or the underlying API data first.
What is the difference between [attr] and [attr=”value”]?
[attr] tests only for attribute presence, while [attr=”value”] requires an exact attribute value.
How do I get an attribute from every matched element?
Iterate with each() and call $(element).attr(‘name’), or use map(…).get() to create an array.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

