Vuoi trasformare la raccolta di dati dal web in un processo stabile, scalabile e “ban‑proof”? Con scraping web n8n paginazione puoi costruire workflow resilienti che navigano tra pagine, gestiscono contenuti caricati via JavaScript e riducono i rischi di blocco. In questa guida pratica impari a scegliere quando basta l’HTTP Request e quando serve il rendering lato client per scraping, come implementare la paginazione in n8n con loop su page/offset/cursor, come mantenere uno stato persistente, deduplicare i record estratti e ridurre ban grazie a rate limiting, caching (ETag/Last‑Modified) e rotazione IP. Vedrai snippet pronti all’uso, configurazioni chiave e un framework per qualità dati (selettori, normalizzazione, tracciabilità), oltre alle considerazioni legali/etiche che spesso vengono ignorate. Obiettivo: passare da script fragili a pipeline solide, schedulate con Cron in n8n e monitorate con alert mirati.

📚 Nuovo a n8n? Parti dalla guida completa: cos'è n8n e come funziona.

[IMG: Canvas n8n con Cron → HTTP Request → Code (extract + nextPage) → IF (hasNext) → HTTP Request (next) → … → DB + Slack alert]


Scegliere lo strumento giusto: HTTP Request, servizi headless o API di terze parti

Non tutti i siti sono uguali e non tutte le strategie di scraping lo sono. La prima decisione è tecnica e strategica.

  • Quando basta HTTP Request

  • La pagina restituisce HTML “statico” o espone un endpoint JSON (spesso usato dal frontend).

  • Paginazione prevedibile tramite query param (page, offset, cursor).

  • Nessuna protezione anti‑bot aggressiva.

  • Quando serve rendering lato client per scraping

  • Contenuti caricati via JavaScript (lazy loading, infinite scroll) senza API pubbliche facili da replicare.

  • Elementi critici generati dopo esecuzione JS (prezzi, disponibilità).

  • In questi casi valuta un servizio headless (browser automatizzato) o un’API di scraping specializzata. Integra in n8n tramite HTTP Request verso il servizio, mantenendo in n8n la logica di orchestrazione, paginazione e salvataggio.

  • Criteri di scelta tra approcci

  • Manutenzione: meno dipendenze esterne = meno costi, ma più fragilità su siti dinamici.

  • Volume e robustezza: siti con protezioni anti‑bot (Cloudflare, fingerprint TLS) richiedono rotazione proxy e IP residenziali, o soluzioni “browser‑like”.

  • Compliance: controlla sempre i termini del sito e le policy robot.txt.

Consiglio operativo: parti con HTTP Request e prova a individuare gli endpoint JSON interni. Se non basta, passa a un servizio di rendering; tieni separata l’estrazione (servizio) dall’orchestrazione (n8n), così il passaggio scala meglio.


Paginazione in n8n: loop su page/offset/cursor con scheduling e rate limiting

La paginazione è il cuore di ogni pipeline di scraping affidabile.

  • Modello con page/offset

  • Costruisci l’URL con query dinamiche (page=1, 2, 3…) o offset (0, 50, 100…).

  • Esegui la richiesta, estrai i risultati, verifica se ci sono più pagine.

  • Modello con cursor/nextPage

  • Alcune API restituiscono un cursore o un link next. Gestiscilo in un nodo Code e decidi se proseguire.

  • Scheduling con Cron in n8n

  • Usa un trigger temporizzato (esecuzione ogni 15 minuti/ogni notte) per avviare il job.

  • Esegui solo delta (ultime novità) se l’origine lo consente.

  • Rate limiting per richieste HTTP

  • Inserisci attese brevi tra batch (1–3 s).

  • Usa “Split In Batches” quando processi molte URL per stabilizzare il throughput.

Esempio (estrazione JSON e controllo nextPage, Code node — Run Once For All Items):

// Input atteso dal nodo precedente: response JSON dell'HTTP Request
const res = $input.first().json;
const items = (res.items || []).map((it) => ({
  json: {
    id: it.id,
    title: it.title?.trim() || '',
    url: it.url || '',
    price: Number(it.price ?? 0),
    source: res.source || 'unknown',
    fetchedAt: new Date().toISOString(),
  }
}));

const hasNext = Boolean(res.nextPage || res.nextCursor);
return [
  { json: { hasNext, next: res.nextPage || res.nextCursor || null } },
  ...items
];

[IMG: HTTP Request configurato con query page={{$json.page}} e nodo Code che calcola hasNext/next]


Stato persistente, cursori e deduplica: evitare doppioni e “ricominciare da dove hai lasciato”

Quando la raccolta è ricorrente, la gestione dello stato è cruciale.

  • Gestione dello stato nello scraping

  • Conserva l’ultimo cursore o la pagina elaborata in uno storage persistente (DB) o nello stato del workflow.

  • Mantieni l’ultima “data di aggiornamento” per estrarre solo le novità.

  • Stato persistente con getWorkflowStaticData(‘global’)

  • Usa uno storage globale del workflow per salvare cursori/ultima pagina. Esempio (Code node — Run Once For All Items):

// Salvataggio/lettura cursore globale
const state = getWorkflowStaticData('global');
const lastCursor = state.lastCursor || null;

const input = $input.first().json;
if (input.newCursor) {
  state.lastCursor = input.newCursor;
}
return [{ json: { lastCursor: state.lastCursor || null } }];
  • Deduplica dei record estratti
  • Definisci una chiave unica (id, slug, url canonical). Prima di salvare, scarta duplicati visti nell’esecuzione corrente e in DB.
// All-items: dedup in memoria per url
const rows = $input.all().map(i => i.json);
const seen = new Set();
const out = [];
for (const r of rows) {
  const key = (r.url || '').trim().toLowerCase();
  if (!key || seen.has(key)) continue;
  seen.add(key);
  out.push(r);
}
return out.map(j => ({ json: j }));
  • Tracciabilità
  • Aggiungi “source”, “fetchedAt” e, se utile, un “hashContent” per rilevare cambiamenti nel tempo.

Contenuti caricati via JavaScript: strategie operative e infinite scroll

Molti siti popolari caricano i dati lato client: servono tattiche diverse.

  • Individua l’endpoint JSON

  • Apri la rete (DevTools) e cerca richieste XHR/fetch che restituiscono i dati. Spesso basta replicarle in HTTP Request in n8n con gli header corretti (cookie/sessione, user‑agent).

  • Infinite scroll

  • La pagina richiama un endpoint con “cursor/after/offset”. Riproduci lo schema: HTTP Request → Code (next) → IF (hasNext) → loop.

  • Rendering lato client per scraping

  • Se i dati non sono esposti, usa un servizio headless con rotazione proxy e fingerprinting del browser. Integra via HTTP Request e mantieni in n8n paginazione, dedup e salvataggio.

  • Lazy loading di immagini/dettagli

  • Spesso ci sono endpoint di dettaglio per ogni item. Accodali a un “Split In Batches” → HTTP Request (dettaglio) → arricchisci i record con i campi mancanti.

[IMG: Diagramma a due fasi: Catalogo (JSON/HTML) → Lista URL → Dettaglio (JSON/HTML) → Merge + Salva]


Antibot e resilienza: Cloudflare, rotazione IP, fingerprint e limiti

  • Protezioni anti‑bot come Cloudflare

  • Evita burst: imposta rate limiting per richieste HTTP con attese tra batch.

  • Usa proxy pool e IP residenziali; alterna user‑agent plausibili e mantieni header coerenti (Accept‑Language, Accept, sec‑ch‑ua).

  • Riduci parallelismo: serializza le chiamate più sensibili.

  • Fingerprinting del browser

  • Alcune difese controllano TLS fingerprint e comportamenti JS. Se fallisci, passa a servizi “browser‑like”.

  • Retry con backoff esponenziale

  • Sui 429/5xx, attiva retry progressivo (2s → 5s → 10s). Interrompi dopo N tentativi e invia alert.

  • Osservabilità

  • Logga gli status code, la latenza media e il tasso di errore per dominio. Monitora i ban nel tempo per calibrare batch e attese.


Parsing sicuro e robusto: selettori, normalizzazione e validazione

  • Selettori CSS/XPath con estrattori

  • Per HTML semplice, identifica pattern stabili (class, id); evita selettori fragili.

  • Se ottieni JSON, preferiscilo: parsing più stabile e veloce.

  • Normalizzazione schema

  • Definisci uno schema di output con tipi coerenti (string/number/date) e campi opzionali.

  • Valida i campi chiave (url, price, title) e imposta default sicuri.

  • Qualità dati e tracciabilità

  • Aggiungi sourceUrl, timestamp, e un checksum del record. Questo aiuta ad auditare e a identificare update reali vs rumore.

Esempio (Code — per‑item: normalizza e mappa)

const j = $json;
return {
  json: {
    id: j.id || j.slug || null,
    title: String(j.title || '').trim(),
    url: String(j.url || '').trim(),
    price: Number(j.price ?? 0),
    currency: j.currency || 'USD',
    fetchedAt: new Date().toISOString(),
    source: j.source || 'unknown'
  }
};

Cache e conditional requests: ETag, Last‑Modified e riduzione dei costi/ban

Riduci richieste inutili e rispetta i limiti.

  • ETag e Last‑Modified

  • Salva ETag/Last‑Modified dal response precedente.

  • Nelle richieste successive, invia If‑None‑Match / If‑Modified‑Since. Se ricevi 304 Not Modified, salta parsing e passa oltre.

  • Come farlo in n8n

  • HTTP Request: aggiungi header dinamici con espressioni (If‑None‑Match: ={{$json.etag}}).

  • Gestisci la logica in un nodo IF: se statusCode==304, non aggiornare; altrimenti prosegui e aggiorna ETag/Last‑Modified persistenze.

  • Benefici

  • Meno banda, meno load sul sito target, minor probabilità di ban.

[IMG: HTTP Request con Headers If‑None‑Match/If‑Modified‑Since e IF che intercetta 304]


Salvataggio e indicizzazione: database, dedup e scheduling/alerting

  • Database di destinazione

  • MongoDB/Postgres: scegli in base a volumi e query. Mongo è flessibile per documenti JSON; Postgres+JSONB per query strutturate e join.

  • Imposta un indice univoco sulla chiave (id/url) per prevenire duplicati lato DB.

  • Deduplica dei record estratti

  • Dedup in memoria (per esecuzione) + indice univoco (persistenza). Logga conflitti e scarti per audit.

  • Scheduling con Cron in n8n

  • Pianifica finestre orarie “soft” (notte/weekend) per scraping massivo.

  • Aggiungi alert: invia un riepilogo Slack con conteggio record nuovi/aggiornati, errori e durata.

  • Pipeline a due fasi

  • Catalogo (lista) → Dettaglio (arricchimento) → Merge → Salva. Questa separazione migliora debug e controlli qualità.


Resilienza end‑to‑end: retry, limiti di concorrenza e aspetti legali/etici

  • Retry con backoff esponenziale

  • Implementa retry solo su errori temporanei. Limita i tentativi e aumenta l’attesa per ogni retry.

  • Limiti di concorrenza

  • Evita chiamate parallele elevate su domini sensibili. Meglio batch piccoli e costanti.

  • Osservabilità

  • Attiva un workflow con Error Trigger per log centralizzato. Traccia tassi di errore per dominio/source.

  • Aspetti legali/etici

  • Rispetta robots.txt, ToS e privacy. Non raccogliere dati personali senza base legale. Fornisci un meccanismo per eliminare dati se richiesto.


Esempio operativo: paginazione con page e arricchimento dettaglio

Scenario: elenco prodotti con endpoint JSON paginato (page=1..N) e endpoint dettaglio per ogni item.

1) Cron (ogni notte)
2) Code (imposta page iniziale, o leggi cursore persistente)
3) HTTP Request (GET lista?page={{$json.page}})
4) Code (estrai items, nextPage)
5) IF (hasNext) → incrementa page → loop al punto 3; altrimenti prosegui
6) Split In Batches (20)
7) HTTP Request (GET dettaglio per item.url)
8) Code (merge campi, normalizza schema)
9) DB (insert/upsert) con indice unico
10) Slack (report)

Snippet per incrementare page (Code — per‑item):

const j = $json;
const nextPage = Number(j.page || 1) + 1;
return { json: { page: nextPage } };

[IMG: Canvas con ramo Lista (loop page) e ramo Dettaglio (Split In Batches) fino al DB]


Quick Takeaways

  • Inizia con HTTP Request e punta agli endpoint JSON; passa al rendering lato client solo quando necessario.
  • Implementa la paginazione in n8n con loop su page/offset/cursor, controlli IF e attese tra batch.
  • Mantieni stato e cursori (getWorkflowStaticData(‘global’) o DB) e applica dedup su chiave unica.
  • Riduci ban con rate limiting, caching via ETag/Last‑Modified e rotazione IP su domini “sensibili”.
  • Normalizza e valida i dati prima del salvataggio; traccia source e fetchedAt per audit.
  • Schedula con Cron e invia alert/summary: osservabilità prima di tutto.

Conclusione

Portare scraping web n8n paginazione a livello “produzione” richiede una combinazione di scelte strategiche e tattiche: puntare prima agli endpoint JSON, orchestrare la paginazione con loop chiari e stato persistente, assicurare qualità e dedup, e proteggere il ciclo con rate limiting, caching e retry intelligenti. Con un disegno a due fasi (lista → dettaglio), salvataggio su DB con indice unico e un layer di observability (Slack report, Error Trigger), i tuoi workflow diventano affidabili e prevedibili. Per i marketer, significa dati freschi e puliti per campagne, pricing intelligence e analisi competitive, senza il peso di manutenzioni continue. Parti da un MVP con pochi endpoint, misura tempi/ban/errori, poi scala con batching e caching: il salto di qualità è nel processo, non solo nel parser.


FAQ

1) Come gestisco la paginazione in n8n senza rischiare loop infiniti?
Controlla sempre un segnale di uscita (no results/hasNext=false). Incrementa page/offset in un Code node, valida i limiti e usa IF per interrompere quando non ci sono più dati.

2) Come tratto contenuti caricati via JavaScript?
Cerca gli endpoint JSON usati dal frontend. Se non esistono o sono offuscati, integra un servizio di rendering lato client e usa n8n per orchestrazione, paginazione e salvataggio.

3) Come riduco i ban su siti protetti (Cloudflare)?
Diminuisci parallelismo, aggiungi attese tra batch, usa proxy/rotazione IP residenziali e header plausibili. Implementa retry con backoff sui 429/5xx e monitora i tassi di errore per dominio.

4) Posso usare caching con ETag/Last‑Modified in n8n?
Sì. Salva ETag/Last‑Modified e inviali come If‑None‑Match/If‑Modified‑Since negli header dell’HTTP Request. Gestisci i 304 per saltare parsing e ridurre richieste.

5) Qual è il modo migliore per evitare duplicati nel database?
Definisci una chiave unica (id/url canonical) e crea un indice unico nel DB. In n8n, aggiungi anche una dedup in memoria per esecuzione, loggando i record scartati.


Ci dai una mano?

Qual è il tuo prossimo target: stabilizzare la paginazione, ridurre i ban con caching/limiti o arricchire i dati con un passo “dettaglio”? Condividi la tua scelta e questo articolo con il team: confrontiamo pattern e trasformiamo gli scraper in pipeline affidabili!

Vuoi automazioni AI su misura per la tua azienda?
Scopri la consulenza →