Use Shifter with Cheerio
Pair Shifter's residential and ISP proxies with Cheerio for fast, lean Node scraping. Cheerio handles the jQuery-style HTML parsing, Shifter handles the residential IPs — no headless browser required.
Quick Start
Install
npm install cheerio axios https-proxy-agent Basic Usage
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
import { load } from "cheerio";
const proxyUrl =
"customer-USERNAME-country-us-sid-123ABC:PASSWORD@p.shifter.io:443";
const { data: html } = await axios.get("https://example.com", {
httpsAgent: new HttpsProxyAgent(proxyUrl),
proxy: false,
});
const $ = load(html);
console.log($("h1").text());
$("article.post").each((_, el) => {
console.log($(el).find("h2").text(), "->", $(el).find("a").attr("href"));
}); Features
Examples
Sticky Session + Multi-Page Crawl
Pin one residential IP for the duration of a multi-page crawl. Add `country-uk` to geo-target and `ttl-300` to extend the sticky window to 5 minutes.
import axios, { type AxiosInstance } from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
import { load } from "cheerio";
import { randomBytes } from "node:crypto";
function makeClient(country: string): AxiosInstance {
const sid = randomBytes(4).toString("hex");
const proxyUrl =
`customer-USERNAME-country-${country}-sid-${sid}-ttl-300:` +
`PASSWORD@p.shifter.io:443`;
return axios.create({
httpsAgent: new HttpsProxyAgent(proxyUrl),
proxy: false,
timeout: 30_000,
headers: {
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"Accept-Language": "en-US,en;q=0.9",
},
});
}
const client = makeClient("uk");
let url: string | null = "https://example.co.uk/products";
const products: { title: string; price: string }[] = [];
while (url) {
const { data: html } = await client.get(url);
const $ = load(html);
$(".product-card").each((_, el) => {
products.push({
title: $(el).find("h2").text().trim(),
price: $(el).find(".price").text().trim(),
});
});
const next = $("a.next-page").attr("href");
url = next ? new URL(next, url).toString() : null;
}
console.log(`Scraped ${products.length} products`); Parallel Scraping (per-request rotation)
Drop the sid for per-request rotation. Each parallel fetch gets a different residential IP — perfect for hitting a list of URLs without tripping per-IP rate limits.
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
import { load } from "cheerio";
function rotatingClient() {
// No sid -> Shifter rotates the residential IP per request.
const proxyUrl =
"customer-USERNAME-country-us:PASSWORD@p.shifter.io:443";
return axios.create({
httpsAgent: new HttpsProxyAgent(proxyUrl),
proxy: false,
timeout: 30_000,
});
}
async function scrape(url: string) {
const client = rotatingClient();
const { data: html } = await client.get(url);
const $ = load(html);
return {
url,
title: $("h1").first().text().trim(),
headings: $("h2").map((_, el) => $(el).text().trim()).get(),
};
}
const urls = [
"https://example.com/category/laptops",
"https://example.com/category/phones",
"https://example.com/category/tablets",
"https://example.com/category/wearables",
];
const results = await Promise.all(urls.map(scrape));
console.log(results); got-scraping (built-in browser fingerprints)
got-scraping bundles realistic header generation on top of got. Pair with Shifter for a tiny, browser-shaped HTTP scraper that's still 100x faster than Puppeteer.
// npm install got-scraping cheerio
import { gotScraping } from "got-scraping";
import { load } from "cheerio";
const proxyUrl =
"customer-USERNAME-country-de-city-berlin-sid-456DEF:PASSWORD@p.shifter.io:443";
const html = await gotScraping({
url: "https://example.de/products",
proxyUrl,
headerGeneratorOptions: {
browsers: [{ name: "chrome", minVersion: 120 }],
devices: ["desktop"],
locales: ["de-DE", "en"],
operatingSystems: ["macos", "linux"],
},
}).text();
const $ = load(html);
$(".product").each((_, el) => {
console.log({
title: $(el).find("h2").text().trim(),
price: $(el).find(".price").text().trim(),
});
}); Crawlee (production crawler with Shifter)
Crawlee (by Apify) handles queues, retries, persistence, and proxy rotation out of the box. Plug Shifter as a ProxyConfiguration and let Crawlee orchestrate the rest.
// npm install crawlee cheerio
import { CheerioCrawler, ProxyConfiguration } from "crawlee";
const proxyConfiguration = new ProxyConfiguration({
newUrlFunction: () => {
// New residential IP per session. Crawlee rotates sessions
// automatically on bans, so stale IPs get cycled out.
const sid = Math.random().toString(36).slice(2, 10);
return `customer-USERNAME-country-fr-sid-${sid}:PASSWORD@p.shifter.io:443`;
},
});
const crawler = new CheerioCrawler({
proxyConfiguration,
maxConcurrency: 8,
async requestHandler({ request, $, enqueueLinks, log }) {
log.info(`${request.url} -> ${$("h1").text().trim()}`);
$(".article").each((_, el) => {
log.info(` ${$(el).find("h2").text().trim()}`);
});
await enqueueLinks({ selector: "a.next-page", strategy: "same-domain" });
},
});
await crawler.run([
"https://example.fr/blog",
"https://example.fr/news",
]); Frequently asked FAQ questions
Common questions about using Shifter with Cheerio.
No. Cheerio is a parser — it doesn't make HTTP requests. The proxy is configured on whichever HTTP client you pair with Cheerio (axios, got, undici, fetch). Once the HTML is fetched through Shifter, you pass it to Cheerio's load() function as usual.
Start Using Shifter with Cheerio
Pair Shifter's 205M+ residential and ISP proxies with Cheerio for fast, lean Node scraping. Per-request rotation, sticky sessions, and full Crawlee support.