Intégration

Utilisez Shifter avec Apify

Intégrez les proxies résidentiels et ISP de Shifter dans n'importe quel acteur Apify -- Crawlee gère la file d'attente et les tentatives répétées, Shifter gère les IP résidentielles. ProxyConfiguration accepte nativement les URL Shifter.

Démarrage rapide

Installer

npm install apify crawlee

Utilisation de base

// main.js (an Apify Actor)
import { Actor } from "apify";
import { CheerioCrawler, ProxyConfiguration } from "crawlee";

await Actor.init();

const proxyConfiguration = new ProxyConfiguration({
  proxyUrls: [
    "customer-USERNAME-country-us-sid-123ABC:PASSWORD@p.shifter.io:443",
  ],
});

const crawler = new CheerioCrawler({
  proxyConfiguration,
  async requestHandler({ request, $, log }) {
    log.info(`${request.url} -> ${$("h1").text().trim()}`);
  },
});

await crawler.run(["https://example.com"]);
await Actor.exit();

Fonctionnalités

Prise en charge native de ProxyConfiguration dans Crawlee — passez une URL Shifter ou une newUrlFunction
Compatible avec CheerioCrawler, PuppeteerCrawler, PlaywrightCrawler et BasicCrawler
IPs persistantes par session via le pool de sessions de Crawlee — les blocages retirent automatiquement les sessions obsolètes
Géociblage dans 195+ pays -- paramétrez le pays via le schéma d'entrée de l'Actor
Intégration directe pour les exécutions planifiées de la console Apify, la mise à l'échelle automatique d'Apify Cloud et Crawlee auto-hébergé
Compatible avec l'ensemble du SDK Apify — pushData, stockage clé-valeur, file de requêtes et persistance des jeux de données

Exemples

Crawlee + Rotation par session

Crawlee gère automatiquement les blocages et l'expiration des sessions. Utilisez newUrlFunction pour générer une nouvelle URL Shifter par session — lorsque Crawlee retire une session en raison d'un blocage, la suivante obtient une nouvelle IP résidentielle.

import { Actor } from "apify";
import { CheerioCrawler, ProxyConfiguration } from "crawlee";

await Actor.init();

const proxyConfiguration = new ProxyConfiguration({
  // Each session asks for a fresh URL — and Crawlee bumps the session
  // on bans, so stale IPs get cycled out automatically.
  newUrlFunction: () => {
    const sid = Math.random().toString(36).slice(2, 10);
    return `customer-USERNAME-country-uk-sid-${sid}-ttl-300:PASSWORD@p.shifter.io:443`;
  },
});

const crawler = new CheerioCrawler({
  proxyConfiguration,
  useSessionPool: true,
  persistCookiesPerSession: true,
  maxConcurrency: 8,

  async requestHandler({ request, $, enqueueLinks, log, session }) {
    log.info(`Session ${session.id} -> ${request.url}`);

    $(".product-card").each((_, el) => {
      // Push to dataset (auto-persisted by Apify)
      Actor.pushData({
        url:   request.url,
        title: $(el).find("h2").text().trim(),
        price: $(el).find(".price").text().trim(),
      });
    });

    await enqueueLinks({ selector: "a.next-page", strategy: "same-domain" });
  },

  failedRequestHandler({ request, log }) {
    log.error(`Failed after retries: ${request.url}`);
  },
});

await crawler.run(["https://example.co.uk/products"]);
await Actor.exit();

PuppeteerCrawler (cibles à fort contenu JS)

Lorsque la cible nécessite un vrai navigateur, remplacez CheerioCrawler par PuppeteerCrawler. La même ProxyConfiguration s'intègre — Crawlee transmet l'URL Shifter dans les arguments de lancement de Puppeteer.

import { Actor } from "apify";
import { PuppeteerCrawler, ProxyConfiguration } from "crawlee";

await Actor.init();

const proxyConfiguration = new ProxyConfiguration({
  newUrlFunction: () => {
    const sid = Math.random().toString(36).slice(2, 10);
    return `customer-USERNAME-country-de-city-berlin-sid-${sid}:PASSWORD@p.shifter.io:443`;
  },
});

const crawler = new PuppeteerCrawler({
  proxyConfiguration,
  useSessionPool: true,
  launchContext: {
    launchOptions: { headless: "new" },
  },
  maxConcurrency: 4,

  async requestHandler({ request, page, log }) {
    log.info(`Visiting ${request.url}`);
    await page.waitForSelector(".product");

    const products = await page.$$eval(".product", (els) =>
      els.map((el) => ({
        title: el.querySelector("h2")?.textContent?.trim(),
        price: el.querySelector(".price")?.textContent?.trim(),
      })),
    );

    await Actor.pushData(products);
  },
});

await crawler.run(["https://example.de/categories/electronics"]);
await Actor.exit();

Actor par pays avec schéma d'entrée

Exposez le pays en tant qu'entrée d'Actor Apify. L'Actor le lit au démarrage et configure Shifter pour le pool résidentiel correspondant. Le même code d'Actor fonctionne pour chaque région.

// .actor/input_schema.json
{
  "title": "Localized Scraper Input",
  "type": "object",
  "schemaVersion": 1,
  "properties": {
    "startUrl": { "type": "string", "title": "Start URL", "default": "https://example.com" },
    "country":  { "type": "string", "title": "Country",   "enum": ["us","uk","de","jp","fr","br"], "default": "us" },
    "maxPages": { "type": "integer", "title": "Max Pages", "default": 100, "minimum": 1, "maximum": 5000 }
  },
  "required": ["startUrl", "country"]
}

// main.js
import { Actor } from "apify";
import { CheerioCrawler, ProxyConfiguration } from "crawlee";

await Actor.init();

const { startUrl, country, maxPages } = await Actor.getInput();

const proxyConfiguration = new ProxyConfiguration({
  newUrlFunction: () => {
    const sid = Math.random().toString(36).slice(2, 10);
    return `customer-USERNAME-country-${country}-sid-${sid}-ttl-300:PASSWORD@p.shifter.io:443`;
  },
});

const crawler = new CheerioCrawler({
  proxyConfiguration,
  maxRequestsPerCrawl: maxPages,
  useSessionPool: true,

  async requestHandler({ request, $, enqueueLinks }) {
    await Actor.pushData({
      country,
      url:   request.url,
      title: $("title").text().trim(),
      h1:    $("h1").first().text().trim(),
    });
    await enqueueLinks({ strategy: "same-domain" });
  },
});

await crawler.run([startUrl]);
await Actor.exit();

SDK Apify hors de Crawlee (logique personnalisée)

Si Crawlee ne correspond pas à votre cas d'usage, vous pouvez tout de même récupérer une URL de proxy Shifter depuis ProxyConfiguration et l'utiliser avec n'importe quel client HTTP. Les sessions, les nouvelles tentatives et la persistance fonctionnent toujours.

import { Actor } from "apify";
import { ProxyConfiguration } from "crawlee";
import { gotScraping } from "got-scraping";

await Actor.init();

const proxyConfiguration = new ProxyConfiguration({
  newUrlFunction: () => {
    const sid = Math.random().toString(36).slice(2, 10);
    return `customer-USERNAME-country-fr-sid-${sid}:PASSWORD@p.shifter.io:443`;
  },
});

// Pull a fresh proxy URL per logical task
async function fetchTarget(url) {
  const proxyUrl = await proxyConfiguration.newUrl();

  const html = await gotScraping({
    url,
    proxyUrl,
    headerGeneratorOptions: {
      browsers: [{ name: "chrome", minVersion: 120 }],
      locales:  ["en-US"],
    },
  }).text();

  return html;
}

const urls = [
  "https://example.fr/api/v1/products?page=1",
  "https://example.fr/api/v1/products?page=2",
  // ...
];

for (const url of urls) {
  try {
    const html = await fetchTarget(url);
    await Actor.pushData({ url, length: html.length });
  } catch (err) {
    console.error(`Failed ${url}: ${err.message}`);
  }
}

await Actor.exit();
FAQ

Questions fréquentes Questions FAQ

Questions fréquentes sur l'utilisation de Shifter avec Apify.

Utilisez la classe ProxyConfiguration de Crawlee avec soit un tableau `proxyUrls` (une ou plusieurs URLs Shifter), soit une `newUrlFunction` qui retourne une nouvelle URL Shifter par session. Passez la configuration à votre crawler — chaque requête est automatiquement acheminée via Shifter.

Commencer

Commencer à utiliser Shifter avec Apify

Exécutez des Actors Apify via les proxies résidentiels et ISP 205M+ de Shifter. Configuration native Crawlee ProxyConfiguration, IPs persistantes par session, et prise en charge complète des crawlers Cheerio / Puppeteer / Playwright.

Essayez Shifter gratuitementConfiguration en quelques minutes. Annulez à tout moment.