Integración

Usa Shifter con Apify

Integra los proxies residenciales y de ISP de Shifter en cualquier Actor de Apify: Crawlee gestiona las colas y los reintentos, Shifter gestiona las IPs residenciales. ProxyConfiguration acepta URLs de Shifter de forma nativa.

Inicio rápido

Instalar

npm install apify crawlee

Uso básico

// 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();

Características

Soporte nativo de ProxyConfiguration en Crawlee: pasa una URL de Shifter o una newUrlFunction
Compatible con CheerioCrawler, PuppeteerCrawler, PlaywrightCrawler y BasicCrawler
IPs persistentes por sesión mediante el pool de sesiones de Crawlee: los bloqueos descartan automáticamente las sesiones obsoletas
Geolocalización en más de 195 países -- parametriza el país mediante el esquema de entrada del Actor
Compatible con ejecuciones programadas en la consola de Apify, autoescalado en Apify Cloud y Crawlee autoalojado
Compatible con todo el Apify SDK: pushData, almacén de clave-valor, cola de solicitudes y persistencia de conjuntos de datos

Ejemplos

Crawlee + Rotación por sesión

Crawlee gestiona los bloqueos y la expiración de sesiones automáticamente. Usa newUrlFunction para generar una nueva URL de Shifter por sesión: cuando Crawlee descarta una sesión por bloqueo, la siguiente obtiene una IP residencial nueva.

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 (objetivos con JavaScript intensivo)

Cuando el objetivo requiere un navegador real, sustituye CheerioCrawler por PuppeteerCrawler. La misma ProxyConfiguration se conecta directamente: Crawlee pasa la URL de Shifter a los argumentos de lanzamiento 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 por país con esquema de entrada

Expón el país como entrada del Actor de Apify. El Actor lo lee al inicio y configura Shifter para el grupo residencial correspondiente. El mismo código del Actor funciona para todas las regiones.

// .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();

Apify SDK fuera de Crawlee (lógica personalizada)

Si Crawlee no se adapta a tu caso, puedes obtener una URL de proxy de Shifter desde ProxyConfiguration y usarla con cualquier cliente HTTP. Las sesiones, los reintentos y la persistencia siguen funcionando.

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();
Preguntas frecuentes

Preguntas frecuentes

Preguntas frecuentes sobre el uso de Shifter con Apify.

Usa la clase ProxyConfiguration de Crawlee con un array `proxyUrls` (una o más URLs de Shifter) o una `newUrlFunction` que devuelva una URL de Shifter nueva por sesión. Pasa la configuración a tu crawler: todas las solicitudes se enrutarán automáticamente a través de Shifter.

Apify Proxy y Shifter son productos independientes. Para usar Shifter, omite la opción `useApifyProxy` y proporciona tu propia ProxyConfiguration con URLs de Shifter. Puedes combinarlos: algunos Actors usan Apify Proxy para el calentamiento y Shifter para los scrapes en producción.

Activa `useSessionPool: true` en tu crawler. Crawlee etiquetará cada solicitud con una sesión y reutilizará la misma URL de proxy (y por tanto el mismo sid de Shifter) en las solicitudes de esa sesión. Cuando una sesión provoca un bloqueo, Crawlee la descarta e inicia una nueva con una IP diferente.

Sí. Define un campo `country` en el archivo input_schema.json de tu Actor y léelo al inicio con `Actor.getInput()`. Incorpóralo al nombre de usuario de Shifter (p. ej. `country-${input.country}`) dentro de tu newUrlFunction. El mismo código del Actor funciona para todas las regiones.

Sí. ProxyConfiguration se integra con los cuatro crawlers de Crawlee: Cheerio, JsdomCrawler, Puppeteer y Playwright. Crawlee gestiona la negociación del proxy de forma transparente, incluida la autenticación en Chromium sin interfaz gráfica.

Sí. La consola de Apify ejecuta el código fuente de tu Actor en su nube. Guarda las credenciales de Shifter como secretos del Actor (Configuración > Variables de entorno), referencialas en tu código mediante `process.env.SHIFTER_USER`, etc., y el Actor enrutará a través de Shifter en cada ejecución programada.

Comenzar

Empieza a usar Shifter con Apify

Ejecuta Apify Actors a través de los proxies residenciales e ISP de más de 205M de Shifter. ProxyConfiguration nativa de Crawlee, IPs persistentes por sesión y soporte completo para crawlers con Cheerio, Puppeteer y Playwright.

Prueba Shifter gratisConfiguración en minutos. Cancela cuando quieras.