דפוס כשל מוכר ב‑Puppeteer הוא שהבקשות הראשונות עוברות כמו שצריך, אבל בהמשך מתחילים לקבל 403 או 429, פסקי זמן, או הגעה לעמוד אתגר. ובכל זאת, הרבה מדריכים עדיין מציגים פרוקסי מתחלפים כאילו מדובר רק בשינוי תצורה של שתי שורות.
זה פשוט לא המצב. הפער בין דוגמה של "להוסיף את הדגל --proxy-server" לבין מערכת שאפשר באמת לתחזק לאורך זמן הוא עצום. המדריך הזה עובר על החלפה ברמת הדפדפן, שערים עם אימות, פיצול דפדפנים או ממסרים חיצוניים, פרופילי דפדפן עקביים, טיפול שגיאות ברמת פרודקשן, וגם על תשובה כנה לשאלה מתי בכלל לא כדאי לנהל פרוקסי בעצמך.
מהו פרוקסי מתחלף ולמה Puppeteer צריך אחד כזה?
פרוקסי יושב בין מופע ה‑Puppeteer שלך לבין האתר שאליו פונים. האתר רואה את כתובת ה‑IP היוצאת של הפרוקסי, לא את המחשב שלך. פרוקסי מתחלף מחליף כתובות IP מתוך מאגר — לפעמים לכל בקשה, לפעמים לכל סשן — כך שהתעבורה שלך לא נראית כמו לקוח אחד שמכה בשרת אלף פעמים ברצף.
ל‑Puppeteer זה רלוונטי במיוחד, כי Chrome במצב headless שמבצע מאות בקשות רצופות מאותה כתובת IP הוא בדיוק הדפוס שמערכות נגד בוטים נועדו לזהות. התיעוד של Cloudflare עצמו מתאר כמה שכבות זיהוי שפועלות במקביל — היוריסטיקות, בדיקות fingerprint ב‑JavaScript, מודלים של למידת מכונה וזיהוי חריגות התנהגותיות. החלפת IP פותרת רק שכבה אחת. רק אחת.
יש שלושה סוגי פרוקסי שכדאי להכיר, והם לא תחליפיים זה לזה:
- פרוקסי דטה־סנטר — זולים, מהירים ומסופקים דרך ספקי אירוח. קל לזהות אותם כי ה‑ASN (בלוק הרשת) ברור כשייך לחוות שרתים ולא לבית פרטי.
- פרוקסי Residential — עוברים דרך ספקיות אינטרנט של משתמשים אמיתיים, ולכן נראים כמו חיבור ביתי רגיל. איטיים ויקרים יותר, אבל הרבה יותר אמינים למראית עין.
- פרוקסי מובייל — כתובות IP של רשתות סלולריות; בדרך כלל האופציה היקרה ביותר, ומתאימה כשבאמת צריך זהות של רשת סלולרית.
כתובות Residential לרוב פחות בולטות מסיווג ASN בלבד מאשר כתובות דטה־סנטר, אבל אף אחת מהקטגוריות לא חסינה לחסימות. אין שיעור זיהוי אוניברסלי: התוצאה תלויה באתר היעד, במוניטין של ה‑IP היוצא, במיקום, בהיסטוריית הסשן, בפרופיל הדפדפן ובהתנהגות הבקשות.
עוד הבחנה שמבלבלת הרבה אנשים: רשימת IP קבועה שאתה מחליף בעצמך (אתה מנהל את המאגר, בוחר את ה‑IP הבא ומטפל בכשלים) שונה מ‑פרוקסי backconnect/gateway (אתה פונה לנקודת קצה אחת, והספק מחליף את ה‑IP היוצא מאחורי הקלעים). שתי הגישות תקפות; הן פשוט מעבירות את המורכבות למקומות שונים.
למה בכלל להגדיר פרוקסי מתחלף ב‑Puppeteer? מקרי שימוש נפוצים
האמת היא: כנראה שלא תצטרך החלפה עד שתצטרך אותה באמת — ואז תצטרך אותה מאוד.
| מקרה שימוש | למה ההחלפה חשובה |
|---|---|
| ניטור מחירים בקטלוגים של מוצרים | בקשות חוזרות לאותו קטלוג מאותה כתובת IP צוברות מגבלות קצב ואותות מוניטין |
| העשרת לידים / חילוץ פרטי קשר | ביקורים חוזרים בפרופילים מאותה כתובת IP נראים כמו סקרייפינג ולא כמו גלישה, ונקלטים במערכות התנהגותיות |
| סקרייפינג של תוצאות חיפוש | מנועי חיפוש הם מהאגרסיביים ביותר בהאטה לפי IP ובהצגת CAPTCHA |
| מודיעין תחרותי | סריקה חוזרת של אותו דומיין לאורך ימים בונה fingerprint שקשור ל‑IP ולהיסטוריית העוגיות שלך |
| צבירת תוכן | הרבה עמודים, ערך נמוך לכל עמוד — בדיוק דפוס תעבורה שמערכות נגד בוטים יודעות לזהות |
אין מספר קבוע שאפשר לצטט כמו "Amazon חוסם בבקשה ה‑51". אתרים לא מפרסמים ספים אוניברסליים, והבקרות יכולות להשתנות לפי נקודת הקצה, מצב החשבון, מוניטין ה‑ASN וצורת התעבורה. התחילו בקצב בקשות נמוך ככל שמותר, בדקו לא רק סטטוסים אלא גם את התוכן עצמו, והוסיפו החלפה רק כשההתנהגות הנמדדת והמדיניות של היעד מצדיקות זאת.
שלוש אסטרטגיות להחלפת פרוקסי ב‑Puppeteer: איזו מהן מתאימה לכם?

זה החלק שרוב המדריכים מדלגים עליו לחלוטין, או גרוע מכך — מציגים רק את הגרסה הגסה ביותר שלו. יש שלוש רמות של גרנולריות, ובחירה שגויה או תבזבז לכם זמן או תסבך משימה פשוטה.
| אסטרטגיית החלפה | רמת גרנולריות | צריך לאתחל מחדש את הדפדפן? | מורכבות | מתאים במיוחד ל |
|---|---|---|---|---|
לכל דפדפן (--proxy-server) | פרוקסי אחד לכל מופע דפדפן | כן | נמוכה | סקרייפינג פשוט ובנפח נמוך |
מנוהל דרך gateway (proxy-chain + endpoint של backconnect) | מדיניות ספק / סשן | לא | בינונית | שערים מתחלפים עם אימות |
| פיצול דפדפנים או relay חיצוני | פרוקסי אחד לכל shard או כלל ניתוב | אין החלפה בתוך אותו תהליך | גבוהה | קונקרנציה מבוקרת וניתוב מדויק |
הערה חשובה לפני שבוחרים: התיעוד של Puppeteer בנושא interception מבהיר ש‑setRequestInterception הוא לא מתג נקי של "החלפת פרוקסי לכל בקשה" — כל בקשה שנקלטה מושהית עד שממשיכים, משיבים או מבטלים אותה במפורש. ניתוב אמיתי לכל בקשה בדרך כלל דורש להעביר את הבקשות דרך gateway מקומי וניתן לתכנות (למשל proxy-chain) במקום לנסות להחליף פרוקסי ישירות בתוך ה‑handler של interception. קחו את זה בחשבון לפני שאתם בוחרים בשיטה 3 בהמשך.
איך מגדירים פרוקסי מתחלף ב‑Puppeteer: מדריך צעד־אחר־צעד
רמת קושי: בינונית
זמן נדרש: כ‑30–45 דקות לכל שלוש השיטות
מה צריך: Node.js 18+, npm, רשימת פרוקסי או חשבון אצל ספק (בפורמט: protocol://user:pass@host:port), והחבילות puppeteer, proxy-chain ו‑puppeteer-extra
דרישות מקדימות: מה צריך לפני שמתחילים
התקינו את החבילות הבסיסיות:
npm install puppeteer proxy-chain puppeteer-extra puppeteer-extra-plugin-stealth
קבלו רשימת פרוקסי מספק (Residential עדיף לכל דבר מעבר לבדיקה מזדמנת) או לכל הפחות כמה פרוקסי ניסוי כדי לאמת את הקוד לפני שאתם שורפים עליו נפח בקשות אמיתי. שמרו פרטי גישה במשתני סביבה — לעולם לא בקוד קשיח, ובטח לא בתוך URL שעלול להיכנס ללוג.
שיטה 1: החלפת פרוקסי לכל דפדפן עם --proxy-server
זו נקודת ההתחלה של כולם, ובצדק — היא צפויה. המסמך של LaunchOptions ב‑Puppeteer מתאר את args כדרך הנתמכת להעביר דגלי שורת פקודה ל‑Chrome, ו‑--proxy-server הוא דגל מקורי של Chromium.
import puppeteer from 'puppeteer';
const proxyPool = [
'http://proxy1.example:8080',
'http://proxy2.example:8080',
'http://proxy3.example:8080',
];
let proxyIndex = 0;
async function scrapeWithRotation(url) {
const proxy = proxyPool[proxyIndex % proxyPool.length];
proxyIndex++;
const browser = await puppeteer.launch({
headless: true,
args: [`--proxy-server=${proxy}`],
});
const page = await browser.newPage();
// אם הפרוקסי דורש אימות, זה חייב לקרות לפני כל ניווט
await page.authenticate({
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS,
});
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
const content = await page.content();
await browser.close(); // סוגרים לפני מעבר לפרוקסי הבא
return content;
}
שימו לב ש‑page.authenticate() מפעיל בשקט request interception מאחורי הקלעים, לפי התיעוד של Puppeteer — זו עלות ביצועים קטנה שכדאי להכיר לפני שמתחילים לתהות למה הכול איטי יותר מהצפוי.
התוצאה הצפויה: כל קריאה מפעילה דפדפן חדש שמקושר לפרוקסי אחר. כדי להחליף, צריך לסגור ולהפעיל מחדש — אין דרך לעקוף את עלות האתחול. עבור סקרייפינג של 50 עמודים, זה יהיה איטי משמעותית משתי השיטות האחרות, רק בגלל זמן ההפעלה של הדפדפן.
מתי להשתמש: סקריפטים עם קונקרנציה נמוכה, משימות חד־פעמיות, ומצבים שבהם פשטות דיבוג חשובה יותר ממהירות.
שיטה 2: שער מתחלף עם אימות באמצעות proxy-chain
Chrome לא מקבל אישורים של user:pass@host ישירות בתוך URL של פרוקסי. החבילה proxy-chain (מתוחזקת על ידי Apify) פותרת את בעיית האימות הזו על ידי הרמת פרוקסי אנונימי מקומי שמעביר הלאה אל הפרוקסי המאומת שלכם. אם ה‑upstream הוא gateway מתחלף או backconnect של ספק, הספק משנה את ה‑IP היוצא מאחורי אותה נקודת קצה בהתאם למדיניות הסשן שלו. proxy-chain עצמו לא מקצה פרוקסי שונה לכל דף קיים ב‑Puppeteer.
import puppeteer from 'puppeteer';
import { anonymizeProxy, closeAnonymizedProxy } from 'proxy-chain';
async function scrapeThroughGateway(upstreamProxyUrl, targetUrl) {
const localProxy = await anonymizeProxy(upstreamProxyUrl);
let browser;
try {
browser = await puppeteer.launch({
headless: true,
args: [`--proxy-server=${localProxy}`],
});
const page = await browser.newPage();
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
return await page.content();
} finally {
if (browser) await browser.close();
await closeAnonymizedProxy(localProxy, true); // תמיד לנקות
}
}
הבלוק finally כאן הוא לא קישוט — שרתי proxy מקומיים שנשארים תלויים דולפים פורטים, וראיתי סקרייפרים שנגמרו להם בשקט descriptors במהלך הלילה כי אף אחד לא סגר את הפרוקסי האנונימי. proxy-chain גם מציף קודי שגיאה ספציפיים (593 לבעיות DNS, 594 לחיבור שנדחה, 597 לכשל אימות) שמאוד עוזרים לסווג תקלות — עוד על זה בהמשך.
מתי להשתמש: שערי Residential / דטה־סנטר מאומתים שבהם ההחלפה נשלטת על ידי endpoint או פרמטרי הסשן של הספק. אם אתם צריכים כמה זהויות פרוקסי קבועות במקביל, עדיף להשתמש בתהליכי דפדפן נפרדים (browser sharding) או ב‑relay חיצוני ייעודי; ל‑Puppeteer עצמו אין תמיכה בפרוקסי שונה לכל דף.
שיטה 3: ניתוב לכל בקשה דורש relay חיצוני
זו האפשרות עם הגרנולריות הגבוהה ביותר — תיאורטית, כל תמונה, סקריפט או קריאת API בעמוד יכולה לצאת דרך IP אחר. בפועל, זו גם הגישה השברירית ביותר והמתועדת פחות, כי interception ב‑Puppeteer נבנה לסינון ושינוי בקשות, לא להחלפת שכבת התעבורה לכל בקשה.
import puppeteer from 'puppeteer';
async function inspectRequests(url) {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', async (request) => {
// בפועל, החלפת פרוקסי אמיתית לכל בקשה דורשת ניתוב
// דרך relay מקומי (proxy-chain) ולא החלפה של תעבורת הדפדפן תוך כדי תנועה —
// Chrome לא תומך בזה.
// ברוב ההטמעות בפרודקשן משתמשים ב-handler הזה כדי לסנן/לבטל
// סוגי משאבים, ובמקביל משלבים browser sharding או gateway.
if (['image', 'font', 'stylesheet'].includes(request.resourceType())) {
request.abort();
} else {
request.continue();
}
});
await page.goto(url, { waitUntil: 'networkidle2' });
await browser.close();
}
בכנות: החלפת IP אמיתית לכל בקשה בתוך Puppeteer לא מסופקת על ידי setRequestInterception(). אם אתם באמת צריכים רמת גרנולריות כזו, ניתבו את Chrome דרך relay חיצוני וניתן לתכנות, או השתמשו במסגרת סקרייפינג שמבוססת מראש על proxy sessions. עבור רוב הפרויקטים, פרוקסי אחד לכל shard של הדפדפן או gateway מתחלף שמנוהל על ידי הספק יהיו קלים יותר לתפעול ולביקורת.
כל שכבת האנטי־זיהוי: פרוקסי מתחלף לבד לא ימנע חסימה
תלונה נפוצה היא: "אני משתמש בפרוקסי ועדיין נחסם." כתובת ה‑IP היא רק אחד מכמה אותות שמערכת בוטים מודרנית יכולה לבחון, והחלפתה כשכל השאר נשאר לא עקבי יכולה דווקא ליצור אנומליה בולטת יותר. דפדפן שטוען שהוא Windows Chrome אבל ה‑client hints, אזור הזמן או ה‑locale שלו אומרים אחרת — הוא דוגמה ברורה לכך.
שכבה 1: פרוקסי Residential מתחלפים
כמו שכבר כוסה — יציאות Residential לרוב אמינות יותר למראית עין מיציאות דטה־סנטר, אבל אין גודל מאגר מינימלי אוניברסלי. התאימו את גודל המאגר לנפח הבקשות הנמדד, לאורך הסשן, לזמני cooldown ולהתנהגות השיתוף של הספק, במקום להמציא מספר IP שרירותי.
שכבה 2: תוסף Stealth להסתרת סימני headless Chrome
puppeteer-extra-plugin-stealth מתקן סט של סימני headless ידועים: navigator.webdriver, מחרוזות vendor של WebGL, אובייקטים חסרים של Chrome runtime, ועוד כמה דליפות CDP. זו באמת שכבת תאימות שימושית, אבל ה‑README של הפרויקט כנה למדי בכך שמדובר במשחק חתול‑ועכבר ושכנראה אי אפשר למנוע הכול. התייחסו לזה כבסיס, לא כהבטחה.
שכבה 3: פרופילי דפדפן עקביים וקצב עבודה אחראי
מחרוזות user-agent צריכות להיות עקביות עם כל מה שהדפדפן מדווח. User-Agent Client Hints של Chrome חושפים נתוני פלטפורמה מובנים, ולכן מחרוזת user-agent שנכתבת ידנית יכולה לסתור את הפלטפורמה בפועל. עדיף להשתמש ב‑user agent שמגיע עם גרסת Chrome המשולבת, לשמור על viewport / locale / timezone יציבים בתוך הסשן, ולהפעיל בקשות בקצב שמרני במקום להמציא fingerprint חדש לכל עמוד.
כך שלוש השכבות נראות יחד באותה תצורת הרצה:
import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
import { anonymizeProxy, closeAnonymizedProxy } from 'proxy-chain';
puppeteer.use(StealthPlugin());
function boundedDelay(minMs = 800, maxMs = 1800) {
return new Promise((r) => setTimeout(r, minMs + Math.random() * (maxMs - minMs)));
}
async function stableProfileScrape(targetUrl, upstreamProxy) {
const localProxy = await anonymizeProxy(upstreamProxy);
let browser;
try {
browser = await puppeteer.launch({
headless: true,
args: [`--proxy-server=${localProxy}`, '--lang=en-US'],
});
const page = await browser.newPage();
await page.setViewport({ width: 1366, height: 768 });
await boundedDelay();
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
return await page.content();
} finally {
if (browser) await browser.close();
await closeAnonymizedProxy(localProxy, true);
}
}
זה הבלוק שרוב המדריכים המתחרים לא מראים — פרוקסי, stealth ורנדומיזציה של fingerprint במקום אחד, מוכן להעתקה ולהתאמה.
טיפול שגיאות וניטור בריאות פרוקסי ברמת פרודקשן

רוב המדריכים נעצרים ברגע שהנתיב השמח עובד. סקרייפינג אמיתי נכשל כל הזמן — פרוקסי נופלים, תוקף אישורים פג, היעד מגביל קצב באמצע ריצה — ושום דבר מזה לא מטופל אם רק מקווים לטוב.
לוגיקת ניסיון חוזר עם backoff אקספוננציאלי ו‑jitter
function backoffMs(attempt, base = 1000, cap = 30_000) {
const exponential = Math.min(cap, base * 2 ** attempt);
return Math.floor(exponential * (0.5 + Math.random() * 0.5)); // jitter מונע עומס סינכרוני
}
async function withRetry(fn, maxRetries = 4) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (err) {
if (attempt === maxRetries) throw err;
const delay = backoffMs(attempt);
console.warn(`Attempt ${attempt + 1} failed: ${err.message}. Retrying in ${delay}ms`);
await new Promise((r) => setTimeout(r, delay));
}
}
}
חסימה אוטומטית של פרוקסי שנכשלו
const proxyStats = new Map(); // proxyUrl -> { success, failure }
function recordResult(proxyUrl, success) {
const stats = proxyStats.get(proxyUrl) || { success: 0, failure: 0 };
success ? stats.success++ : stats.failure++;
proxyStats.set(proxyUrl, stats);
}
function isHealthy(proxyUrl) {
const stats = proxyStats.get(proxyUrl);
if (!stats) return true;
const total = stats.success + stats.failure;
if (total < 5) return true; // עדיין אין מספיק נתונים
return stats.failure / total < 0.5; // חוסמים אם שיעור הכשלים עובר 50%
}
function getHealthyProxy(pool) {
const healthy = pool.filter(isHealthy);
if (healthy.length === 0) throw new Error('No healthy proxies remaining in pool');
return healthy[Math.floor(Math.random() * healthy.length)];
}
עקבו אחרי סוג השגיאה, לא רק הצלחה/כישלון — 407 (אישורים שגויים) ו‑429 (הגבלת קצב) דורשים תגובות שונות לחלוטין. להכות שוב ושוב בפרוקסי שנכשל באימות רק שורף זמן; הפתרון הוא לבדוק את האישורים, לא להחליף מהר יותר.
פתרון תקלות נפוצות בפרוקסי מתחלף ב‑Puppeteer
| שגיאה | סיבה סבירה | פתרון |
|---|---|---|
ERR_PROXY_CONNECTION_FAILED | הפרוקסי לא פעיל או לא נגיש | להסיר מהמאגר, לנסות את הפרוקסי הבא |
407 Proxy Authentication Required | אישורים שגויים או סוג אימות לא נתמך | לבדוק את אישורי page.authenticate(); להשתמש ב‑proxy-chain לאימות דרך URL |
TimeoutError | פרוקסי איטי או חסימה מצד היעד | להאריך timeout; לעבור לפרוקסי Residential |
403 Forbidden | ה‑IP או ה‑fingerprint סומנו | להחליף פרוקסי + להפעיל stealth + לרנדמז user-agent |
ERR_TUNNEL_CONNECTION_FAILED | בעיית מנהרת HTTPS | לבדוק תמיכה ב‑CONNECT; לנסות tunneling מקומי דרך proxy-chain |
עוד כמה דברים שכדאי לדעת ולא נכנסים יפה לטבלה: קוד מצב 200 לא אומר בהכרח שהכול הצליח. חסימות רכות מחזירות לעיתים עמוד HTML מלא — מסך התחברות או מסך אתגר — עם קוד סטטוס רגיל, לכן צריך לאמת את התוכן בפועל ולא רק את הסטטוס. ואם אתם תקועים, מדריך הדיבוג של Puppeteer ממליץ להריץ עם headless: false, להוסיף slowMo, ולהגדיר NODE_DEBUG="puppeteer:*" כדי לקבל לוגים מפורטים של הפרוטוקול — רק שימו לב שהלוגים האלה עלולים לכלול נתוני בקשה רגישים, אז אל תשאירו אותם פעילים מול פרטי ייצור.
השוואה בין ניהול פרוקסי עצמאי, gateway של ספק ו‑API לחילוץ בעזרת AI
| קריטריון | ניהול עצמי של רשימת פרוקסי | Backconnect Gateway (Bright Data, Oxylabs, Decodo) | API לחילוץ בעזרת AI (Thunderbit) |
|---|---|---|---|
| עלות (נפח נמוך) | נמוכה עד בינונית | בינונית–גבוהה לפי GB | נמוכה (תוכנית חינמית, ואז לפי שימוש) |
| אמינות | תלויה בבדיקות הבריאות שלכם | גבוהה (מנוהל על ידי הספק) | גבוהה (תשתית מנוהלת) |
| אנטי־זיהוי | DIY — אתם בונים את זה | חלקי (רק החלפת IP) | מובנה |
| פלט מובנה | לא (HTML גולמי) | לא (HTML גולמי) | כן (JSON לפי סכימה) |
| זמן הקמה | שעות | דקות | דקות |
| שליטה | מלאה | מוגבלת ל‑API של הספק | מוגבלת למודל הסכימה |
מחירי הספקים נכון לעכשיו (נבדק ב‑2026-08-07) נותנים תחושה לגבי עקומת העלות של אופציית ה‑gateway: התמחור של Bright Data לפרוקסי Residential מציע תשלום לפי שימוש ותוכניות נפח שהמבצעים שלהן יכולים להשתנות; Oxylabs מציגה $6/GB ב‑5 GB ו‑$2.50/GB ב‑1 TB; ו‑Decodo (לשעבר Smartproxy) מציגה $3.75/GB ב‑3 GB, $2.75/GB ב‑100 GB, והצעת pay-as-you-go של $4/GB. Decodo גם מפרסמת מאגר של יותר מ‑115M כתובות IP ושיעור הצלחה של 99.92% — טענות ספק, לא מדדים שאומתו באופן עצמאי.
עץ ההחלטה שאני באמת משתמש בו: האם אתם צריכים אינטראקציה עם העמוד — קליק, גלילה, מילוי טפסים, שמירת סשן התחברות? בנו עם Puppeteer ופרוקסי. האם אתם צריכים רק את הנתונים שכבר נמצאים בעמוד? בדקו API לחילוץ לפני שאתם בונים תשתית פרוקסי שתצטרכו לתחזק לנצח.
מתי Puppeteer + פרוקסי הוא יותר מדי: עדיף לחלץ נתונים מובנים עם API
מתישהו סביב הפעם השלישית שבניתי מחדש מערכת בדיקת בריאות לפרוקסי עבור פרויקט שבכלל רק היה צריך מחירי מוצרים בגיליון, זה התחבר לי: רוב התשתית הזו קיימת כדי לפתור בעיה — להוציא HTML גולמי מהעמוד — שהיא בכלל לא המטרה של המפתח. המטרה היא נתונים מובנים. HTML הוא רק פורמט ביניים מעצבן.
Thunderbit Open API מתייחס לחילוץ כפעולה העיקרית, לא כתוצר לוואי של אוטומציית דפדפן. POST /extract מקבל URL ו‑JSON Schema, ומחזיר נתונים מובנים תואמים — תוך טיפול ברינדור JavaScript, באמצעי אנטי־בוט וב‑CAPTCHA בצד השרת, במקום שתצטרכו לחבר בעצמכם stealth plugins ומאגרי פרוקסי:
curl -X POST https://openapi.thunderbit.com/openapi/v1/extract \
-H "Authorization: Bearer $THUNDERBIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/product",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"price": {"type": "number"}
},
"required": ["name", "price"]
}
}'
יש גם נקודת קצה POST /distill למקרים שבהם אתם רוצים Markdown נקי במקום סכימה קשיחה, ותמיכה בחילוץ אצווה כדי להריץ את אותה סכימה על כמה URLs בקריאה אחת. לפי התמחור הנוכחי של Thunderbit API, Distill עולה יחידה אחת לעמוד ו‑Extract עולה 20 יחידות לעמוד — והתוכנית החינמית כוללת 600 יחידות חד־פעמיות, מספיק כדי לבדוק את הזרימה לפני התחייבות.
למפתחים שעובדים בתוך Claude, Cursor או לקוח אחר שתומך ב‑MCP, Thunderbit גם מציע את thunderbit_extract ו‑thunderbit_distill ככלי MCP, כך שסוכן יכול להחליט תוך כדי משימה מתי צריך למשוך מידע מהעמוד במקום לדרוש שלב סקרייפינג נפרד. הייתי בודק את מפרט ה‑API החי לפני שמחברים הגדרת MCP, כי שמות הכלים והפרמטרים יכולים להשתנות בין גרסאות תיעוד.
| ממד | Puppeteer + פרוקסי מתחלף | Thunderbit API |
|---|---|---|
| מורכבות הקמה | גבוהה — מאגר פרוקסי, לוגיקת החלפה, stealth, ניסיונות חוזרים | נמוכה — קריאת API אחת עם JSON Schema |
| טיפול באנטי־בוט | ידני | מובנה |
| פלט | HTML גולמי (דורש parsing) | JSON מובנה לפי הסכמה שלכם |
| תחזוקה | גבוהה — selectors נשברים, פרוקסי מתקלקלים | נמוכה |
| הכי מתאים ל | אוטומציה מותאמת, זרימות התחברות, אינטראקציות ייחודיות | חילוץ נתונים בהיקף גדול |
למען ההגינות לגישה העצמאית: אם המקרה שלכם כולל התחברות לחשבון, מעבר על flow רב־שלבי, או כל דבר שדורש שמירת מצב לאורך סשן, בדרך כלל API לחילוץ לא יחליף את זה — ה‑FAQ של Thunderbit אומר במפורש שזרימות התחברות אינטראקטיביות עדיין לא נתמכות דרך ה‑API. שם Puppeteer יחד עם פרוקסי עדיין מנצחים. אבל אם המשימה היא "להוציא נתונים מהרבה עמודים ציבוריים לתוך סכימה שהגדרתי", בניית סטאק פרוקסי משלכם פותרת בעיה קשה יותר מזו שבאמת יש לכם. לצוותים שמעדיפים לוותר על הקוד לגמרי, תוסף Chrome של Thunderbit מציע את אותה חילוץ מבוסס AI בממשק קליק‑ולחץ — שווה לבדוק אם אתם שוקלים web scraping ללא קוד מול סביבת פיתוח מלאה.
מסקנות עיקריות
פרוקסי מתחלף ב‑Puppeteer הוא לא טכניקה אחת. החלפה לכל דפדפן פשוטה ומבודדת. gateway מאומת ומתחלף יכול להחליף יציאות מאחורי נקודת קצה אחת לכל הדפדפן. זהויות מדויקות יותר, לכל בקשה או במקביל, דורשות browser sharding או relay חיצוני; interception של בקשות לבדו לא משנה את מסלול הרשת של Chrome.
אבל בלי שאר הסטאק, זה לא באמת משנה. פרוקסי פותרים בעיית מוניטין IP; תוספי stealth ועקביות של fingerprint פותרים בעיית אותות דפדפן; jitter וקצב נכון פותרים בעיית התנהגות. דלגו על אחת השכבות ועדיין תישארו חשופים לחסימה — פשוט מסיבה אחרת.
אם אתם בונים את זה בעצמכם, התחילו עם מאגר proxy-chain ועם קטעי הקוד למעלה — הם יקחו אתכם רחוק יותר מרוב הקורסים בתשלום. אם אתם מעדיפים לדלג לגמרי על ניהול פרוקסי ופשוט לקבל נתונים מובנים, מסמכי ה‑API של Thunderbit שווים עשר דקות מזמנכם לפני שתשקיעו סוף שבוע בבניית תשתית בדיקות בריאות שתצטרכו לתחזק לנצח. כל מסלול לגיטימי — רק ודאו שאתם פותרים את הבעיה שבאמת יש לכם, ולא את זו שכל מדריך מניח שיש לכם. למבט רחב יותר על האופן שבו AI משנה את התחום, קראו את ההעמקה שלנו בנושא AI web scraping ואיך הוא משתווה לגישות מסורתיות.
שאלות נפוצות
כל כמה זמן כדאי להחליף פרוקסי ב‑Puppeteer?
זה תלוי בכמה אגרסיבית ההגבלת קצב של היעד. באתרים עם זיהוי בוטים קשוח, עדיף להחליף לכל עמוד או לכל סשן. באתרים סלחניים יותר, החלפה לכל סשן או אפילו IP אחד קבוע לכל ריצה יכולה לעבוד מצוין. אין מספר אוניברסלי — התייחסו ל‑403, ל‑429 ול‑timeouts כסימן להחליף בתדירות גבוהה יותר, לא כמספר בקשות קבוע.
אפשר להשתמש בפרוקסי חינמיים לסקרייפינג עם Puppeteer?
טכנית כן, אבל לא הייתי ממליץ על זה מעבר לבדיקות מהירות. רשימות פרוקסי חינמיות בדרך כלל איטיות, לא יציבות, ולעיתים קרובות כבר חסומות אצל האתרים שאתם מנסים לסרוק. לכל שימוש פרודקשני, פרוקסי Residential מספק בתשלום או gateway מנוהל שווים את העלות.
האם puppeteer-extra-plugin-stealth עובד מול כל מערכות האנטי־בוט?
לא, וגם התיעוד של התוסף אומר זאת במפורש. הוא מפחית כמה סימני headless נפוצים, אבל היעד עדיין יכול לבדוק מוניטין רשת, מאפייני TLS, עוגיות, client hints והתנהגות. התייחסו לתוסף כשכבת תאימות אחת, לא כהבטחה.
מה ההבדל בין proxy-chain לבין --proxy-server ב‑Puppeteer?
--proxy-server הוא דגל מקורי של Chromium שמקצה נקודת פרוקסי אחת לכל מופע דפדפן, ו‑Chrome לא מקבל שם אישורי פרוקסי מוטמעים. proxy-chain יוצר מנהרה מקומית ואנונימית אל upstream מאומת. ההחלפה עצמה מגיעה מהפעלה מחדש עם upstream אחר, מ‑backconnect gateway שמנוהל על ידי הספק, או מ‑relay אחר שתכננתם — לא מכך ש‑proxy-chain מקצה פרוקסי לכל דף ב‑Puppeteer.
האם פרוקסי מתחלף מספיק כדי להימנע מחסימות לחלוטין?
לא — וזו הטעות הנפוצה ביותר. מערכות אנטי־בוט מודרניות כמו Cloudflare bot management משלבות מוניטין IP עם fingerprint של הדפדפן, דפוסי התנהגות והיסטוריית סשן. פרוקסי פותרים את רכיב מוניטין ה‑IP; עדיין צריך תצורת stealth, fingerprints עקביים ותזמון מציאותי כדי לא להיתפס באותות אחרים.
למידע נוסף


