בשבוע שעבר ביזבזתי כמות מביכה של זמן על בהייה בתגובת 407 Proxy Authentication Required, כשאני משוכנע שספק ה-proxy שלי תקול. מסתבר שהגדרתי את פרטי ההזדהות על המאפיין הלא נכון — תיקון של שתי שורות שלקח לי שעתיים למצוא. אם זה נשמע לכם מוכר, המדריך הזה בשבילכם.
הגדרת proxy עם HttpClient ב-C# היא אחד מאותם נושאים שבהם הדפוס הבסיסי פשוט, אבל דווקא המלכודות שצצות בפרודקשן — מיצוי סוקטים (socket exhaustion), אי-התאמות בגרסאות SOCKS5, בלבול בפרטי הזדהות — גוזלות זמן אמיתי.
אני עובד כבר לא מעט זמן עם כלי web scraping וחילוץ נתונים ב-Thunderbit, וראיתי את אותן טעויות חוזרות שוב ושוב — גם בדיונים ההנדסיים הפנימיים שלנו וגם בקהילות המפתחים שאנחנו עוקבים אחריהן. הסקירה הזו מכסה את כל המסלול: הקמה, אימות, רוטציית proxy, בחירת פרוטוקול, וטבלת פתרון תקלות שבאמת הייתי שמח שתהיה קיימת ביום שבו התחלתי.
רמת קושי: מתחילים עד בינוני
זמן נדרש: כ-15 דקות למעקב אחר המדריך, יותר מזה לדפוסי רוטציה בפרודקשן
מה תצטרכו: .NET 6+ SDK (עבור SOCKS5 ותכונות handler מודרניות; .NET Framework 4.x עובד לדוגמאות proxy בסיסיות מעל HTTP), עורך קוד, ולפחות נקודת קצה אחת של proxy לבדיקות
מה זה HttpClient ולמה הוא צריך proxy?

HttpClient היא המחלקה המובנית של .NET במרחב System.Net.Http לשליחת בקשות HTTP וקבלת תגובות. היא תומכת ב-async/await, בכותרות מותאמות אישית, ב-cancellation tokens ובקונפיגורציה מבוססת handler. מיקרוסופט מתארת אותה כ-מחלקה לשליחת בקשות HTTP וקבלת תגובות HTTP ממשאב המזוהה על ידי URI.
שרת proxy הוא מתווך שיושב בין האפליקציה שלכם לבין אתר היעד. כשאתם מנתבים תעבורה דרך proxy, היעד רואה את כתובת ה-IP של ה-proxy במקום את שלכם.
ל-HttpClient עצמו אין מאפיין Proxy. ניתוב ה-proxy מוגדר על ה-handler שמתחתיו — או HttpClientHandler או SocketsHttpHandler — שמקבל מופע של WebProxy. המודל המנטלי נראה כך:
[Your C# App] → [HttpClient + Handler] → [Proxy Server] → [Target Website]
בגלל זה "להחליף proxy על HttpClient חי" הוא בעיית תכנון, לא סתם השמה למאפיין. על כך בהרחבה בפרק הרוטציה.
נסו את Thunderbit לחילוץ נתונים קל יותר
למה להשתמש ב-proxy עם HttpClient ב-C#
מפתחים מנתבים תעבורת HttpClient דרך proxy מכמה סיבות חוזרות, וסוג ה-proxy הנכון תלוי במשימה.
- הימנעות מחסימות IP ומהגבלות קצב: קריטי ל-web scraping, לייצור לידים או לניטור מחירים בקנה מידה גדול. כתובת IP בודדת שמפציצה אתר תיחסם מהר מאוד.
- עקיפת הגבלות גיאוגרפיות: גישה ל-API או לתוכן שנעולים לאזור מסוים, על ידי ניתוב דרך proxy במדינות ספציפיות.
- הסתרת כתובת ה-IP המקורית שלכם: שכבת פרטיות נוספת לאיסוף נתונים רגישים או למחקר תחרותי.
- דרישות ארגוניות או רגולטוריות: ארגונים רבים מחייבים שכל התעבורה היוצאת תעבור דרך שער מרכזי לצורך תיעוד וממשל.
- בדיקות ו-QA: הדמיית בקשות ממיקומים שונים או מתנאי רשת שונים, בלי לפרוס תשתית פיזית באותם אזורים.
| תרחיש שימוש | בחירת proxy אופיינית | למה זה מתאים |
|---|---|---|
| Web scraping בקנה מידה גדול | Rotating residential proxies | מגוון IP רחב יותר, קשה יותר למערכות anti-bot לסווג |
| ניטור מחירים במסחר אלקטרוני | Residential או datacenter עם מיקוד גיאוגרפי | בדיקות מחירים ומלאי ספציפיים לאזור |
| גישה ל-API דרך שער קבוע | Datacenter proxy או proxy ארגוני | רשימת IP מאושרת וצפויה, עלות נמוכה יותר |
| ציות ורגולציה ארגונית | System proxy, PAC proxy, proxy ארגוני עם אימות | תיעוד מרכזי ובקרה על תעבורה יוצאת |
| בדיקות QA ולוקליזציה | מאגר proxy לפי מדינה | מדמה גישת משתמש אמיתי מאזורי היעד |
השימוש ב-proxy גם גדל בשלבים צפויים. מתחילים עם proxy סטטי בודד כדי לוודא שהניתוב עובד. scraper בפרודקשן עובר למאגר, וממפה בקשות ל-proxy לפי דומיין יעד, גיאוגרפיה או שיעור כשלים. צוותים בשלים עוברים לא פעם לשער proxy מנוהל, שבו רוטציה, ניסיונות חוזרים והצמדת סשן מטופלים מאחורי נקודת קצה אחת.
רוטציית proxy אינה פתרון קסם. אם היעד חוסם התנהגות חשודה, החלפת כתובות IP תעזור רק אם גם קצב הבקשות, הכותרות, ה-cookies וטביעת האצבע של TLS מטופלים בזהירות.
איזו גרסת .NET תומכת במה: מטריצת תאימות מהירה
העתקה של קטע קוד proxy מפוסט בבלוג אל תוך framework יעד לא מתאים היא מקור מרכזי לכשלים שקטים. קו השבר הגדול ביותר הוא בין .NET Framework 4.x לבין .NET המודרני (.NET 6+). הנה מה עובד היכן:

| יכולת | .NET Framework 4.x | .NET 6 | .NET 7 | .NET 8–9 |
|---|---|---|---|---|
WebProxy + HttpClientHandler | כן | כן | כן | כן |
SOCKS5 באמצעות WebProxy("socks5://...") | לא | כן (נוסף ב-.NET 6) | כן | כן |
SocketsHttpHandler (ה-handler שברירת המחדל) | לא | כן | כן | כן |
HttpClient.DefaultProxy סטטי | לא | כן | כן | כן |
PooledConnectionLifetime | לא | כן | כן | כן |
אם אתם מכוונים ל-.NET Framework 4.x, הישארו עם proxy מסוג HTTP/HTTPS יחד עם HttpClientHandler ו-WebProxy. SOCKS5 ובקרות pooling מודרניות דורשות .NET 6 ומעלה.
התנהגות עדינה אחת שכדאי לשים לב אליה: HttpClient.DefaultProxy הוא מאפיין סטטי ב-.NET המודרני. אם הוא נקבע בקוד אתחול משותף או יורש ממשתני סביבה כמו HTTPS_PROXY או HTTP_PROXY, כל מופע של HttpClient יאמץ אותו — אלא אם תדרסו את ה-handler במפורש. בפריסות מבוססות קונטיינרים זהו מקור נפוץ לבלבול מסוג "למה הלקוח שלי משתמש ב-proxy שמעולם לא הגדרתי?".
שלב 1: יצירת פרויקט Console חדש ב-C#
פתחו טרמינל וייצרו פרויקט חדש:
dotnet new console -n ProxyHttpClientDemo
cd ProxyHttpClientDemo
ודאו את גרסת ה-SDK שלכם עם dotnet --version. הדוגמאות במדריך הזה מכוונות ל-.NET 6+ לכיסוי מלא של התכונות. אם אתם צריכים את גרסת ה-LTS העדכנית של ה-SDK, הורידו אותה מ-עמוד ההורדות של מיקרוסופט.
פתחו את Program.cs בעורך שלכם. שם קורה כל הקסם.
שלב 2: ביצוע בקשת HTTP בסיסית (ללא proxy)
לפני שמגדירים proxy, קבעו מהי כתובת ה-IP האמיתית שממנה אתם יוצאים. כך, ברגע שה-proxy יופעל, תוכלו לוודא שה-IP באמת השתנה.
using System.Net.Http;
using var client = new HttpClient();
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine($"Direct IP: {ip}");
הריצו את זה. אתם אמורים לראות את כתובת ה-IP הציבורית הנוכחית שלכם, משהו כזה:
Direct IP: 203.0.113.10
שמרו את הערך הזה בראש. אחרי השלב הבא, הוא אמור להיות שונה.
שלב 3: הגדרת WebProxy עם HttpClientHandler
הדפוס הקנוני מורכב משלושה אובייקטים: WebProxy, handler, והלקוח.
using System.Net;
using System.Net.Http;
var proxy = new WebProxy("http://proxy.example.com:8080")
{
BypassProxyOnLocal = false
};
var handler = new HttpClientHandler
{
Proxy = proxy,
UseProxy = true,
UseDefaultCredentials = false
};
using var client = new HttpClient(handler);
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine($"Proxy IP: {ip}");
החליפו את proxy.example.com:8080 בנקודת הקצה האמיתית של ה-proxy שלכם. אם הכול מחובר נכון, ה-IP שיודפס צריך להתאים כעת ל-IP היציאה של ה-proxy — ולא ל-IP האמיתי שלכם.
מאפיינים מרכזיים שכדאי להבין:
Proxy— מופע ה-IWebProxyשה-handler משתמש בו לניתוב.UseProxy = true— אומר ל-handler באמת להשתמש ב-proxy שהוגדר. (נשמע מובן מאליו, אבל שכחה של זה היא בזבוז זמן דיבוג אמיתי.)BypassProxyOnLocal = false— מונע מה-handler לדלג על ה-proxy עבור יעדים שנראים "מקומיים".UseDefaultCredentials— שולט בשאלה האם ה-handler שולח את פרטי ההזדהות המוגדרים כברירת מחדל ב-Windows. זה לא אותו דבר כמו שם משתמש/סיסמה של ה-proxy.

שלב 4: הוספת אימות proxy עם NetworkCredential
רוב ספקי ה-proxy בתשלום דורשים פרטי הזדהות. הדפוס הנכון הוא להגדיר אותם על אובייקט ה-WebProxy עצמו:
using System.Net;
using System.Net.Http;
var proxy = new WebProxy("http://proxy.example.com:8080")
{
Credentials = new NetworkCredential("proxy-user", "proxy-password")
};
var handler = new HttpClientHandler
{
Proxy = proxy,
UseProxy = true
};
using var client = new HttpClient(handler);
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine($"Authenticated proxy IP: {ip}");
ספקים רבים נותנים לכם פורמט URL כמו http://username:password@host:port. בקוד .NET, עדיף להשתמש ב-NetworkCredential מאשר להטמיע פרטי הזדהות בתוך מחרוזת ה-URI. זה חוסך בעיות escaping עם תווים מיוחדים בסיסמאות, ושומר על הפרדה ברורה בין ה-URI לבין פרטי ההזדהות.
את טעות האימות הנפוצה ביותר — ולמה היא גורמת לשגיאות 407 — אכסה בפרק ייעודי בהמשך.
שלב 5: ייצוא או שימוש בנתוני התגובה
לכל דבר מעבר לבדיקת IP מהירה, טפלו בתגובה כמו שצריך:
using var response = await client.GetAsync("https://example.com/api/products");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine($"Request failed: {(int)response.StatusCode} {response.ReasonPhrase}");
return;
}
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
בתהליכי scraping, הבקשה דרך ה-proxy היא רק שכבת התעבורה. עדיין נדרשים פענוח, נרמול, הסרת כפילויות, ניסיונות חוזרים וייצוא ל-Excel, Google Sheets, מסדי נתונים או יעדים אחרים. כלים כמו Thunderbit יכולים לאוטמט את שלבי החילוץ והייצוא — תוסף ה-Chrome שלו מטפל בחילוץ נתונים מובנים ובייצוא חינמי ל-Google Sheets, Excel, Airtable או Notion, בלי שתצטרכו לכתוב קוד פענוח.
ייצאו נתונים שנאספו ל-Excel, Sheets, Airtable או Notion Get Started Free
פרטי הזדהות של proxy מול פרטי הזדהות של שרת: הטעות שגורמת לשגיאות 407

ראיתי את הטעות הזו בשרשורים ב-Stack Overflow, בפוסטים ב-Microsoft Q&A, ו — בגילוי נאות מלא — בקוד שלי עצמי.
ההבחנה פשוטה אבל קל להתבלבל בה:
- פרטי הזדהות של proxy מאמתים אתכם מול שרת ה-proxy עצמו.
- פרטי הזדהות של שרת מאמתים אתכם מול שרת היעד.
ב-HttpClientHandler, השניים יושבים על מאפיינים שונים. הגדרה על המאפיין הלא נכון היא הסיבה מספר 1 לשגיאות 407 Proxy Authentication Required.
// ❌ שגוי — מגדיר פרטי הזדהות עבור שרת היעד, לא עבור ה-proxy
handler.Credentials = new NetworkCredential("user", "pass");
// ✅ נכון — מגדיר פרטי הזדהות על אובייקט ה-proxy עצמו
handler.Proxy = new WebProxy("http://proxy:8080")
{
Credentials = new NetworkCredential("user", "pass")
};
HttpClientHandler.Credentials מכוון ליעד. WebProxy.Credentials מכוון ל-proxy. אם ה-proxy מחזיר 407, מקומם של פרטי ההזדהות שלכם הוא על ה-proxy.
עוד מלכודת: HttpClientHandler.PreAuthenticate שולט בהתנהגות אימות מקדים מול שרת היעד. הוא אינו שולט בכותרת Proxy-Authorization. אל תשתמשו בו כפתרון ל-407.
איך לבצע רוטציית proxy עם HttpClient ב-C#
מפתחים שואלים את זה בלי הפסקה בפורומים. התשובה מאכזבת בהתחלה: אי אפשר להחליף את ה-proxy על מופע HttpClient חי. ה-proxy יושב על ה-handler. ה-handler נקבע בזמן הבנייה. HttpClient לא חושף מאפיין Proxy שניתן לשינוי.
העקיפה הנאיבית — new HttpClient(new HttpClientHandler { Proxy = ... }) לכל בקשה — יוצרת בעיה אחרת. מיקרוסופט מזהירה במפורש שיצירה והשמדה של לקוחות לכל בקשה עלולות למצות את פורטי ה-TCP הזמינים, מכיוון שפורטים אינם משתחררים מיד לאחר סגירת החיבור.

אז הנה שלושה דפוסים ברמת פרודקשן שבאמת עובדים.
אפשרות 1: לקוחות בעלי שם דרך IHttpClientFactory
אם קבוצת ה-proxy שלכם ידועה כבר באתחול, לקוחות בעלי שם הם האפשרות הפשוטה ביותר. כל לקוח בעל שם מקבל תצורת handler משלו, וקוד האפליקציה מאתר אותו לפי שם בזמן ריצה.
builder.Services.AddHttpClient("proxy-us")
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
Proxy = new WebProxy("http://us-proxy.example.com:8080")
{
Credentials = new NetworkCredential("user", "pass")
},
UseProxy = true
});
builder.Services.AddHttpClient("proxy-eu")
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
Proxy = new WebProxy("http://eu-proxy.example.com:8080")
{
Credentials = new NetworkCredential("user", "pass")
},
UseProxy = true
});
// בזמן הבקשה:
var client = httpClientFactory.CreateClient("proxy-us");
ה-factory מנהל את מחזורי החיים של ה-handlers ומונע את ה-anti-pattern של לקוח חדש לכל בקשה.
אפשרות 2: SocketsHttpHandler + PooledConnectionLifetime (.NET 6+)
עבור לקוח ארוך-חיים שעובד מול שער proxy שמחליף כתובות IP יציאה בכל חיבור חדש, PooledConnectionLifetime מאלץ יצירה מחדש של חיבורים לאחר משך זמן מוגדר.
var handler = new SocketsHttpHandler
{
Proxy = new WebProxy("http://rotating-gateway.example.com:8080")
{
Credentials = new NetworkCredential("user", "pass")
},
UseProxy = true,
PooledConnectionLifetime = TimeSpan.FromMinutes(5)
};
using var client = new HttpClient(handler);
זה לא משנה בקסם את אובייקט ה-Proxy בכל בקשה. זה עובד הכי טוב עם שערי proxy שמקצים כתובת IP יציאה שונה בכל חיבור TCP חדש, או עם מאגרי proxy מבוססי DNS שבהם שם המארח נפתר לנקודות קצה שונות לאורך זמן.
אפשרות 3: DelegatingHandler מותאם לבחירת proxy מתקדמת
כאשר בחירת ה-proxy תלויה בכתובת ה-URL של הבקשה, ב-payload או בהקשר זמן ריצה, handler ניתוב מותאם יכול לבחון כל בקשה ולהעביר אותה לצינור ה-handler הפנימי הנכון.
public sealed class ProxyRoutingHandler : DelegatingHandler
{
private readonly IReadOnlyDictionary<string, HttpMessageInvoker> _clients;
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var key = SelectProxyKey(request);
return _clients[key].SendAsync(request, cancellationToken);
}
}
זהו תכנון מתקדם. בטיחות תהליכונים (thread safety), שחרור משאבים, שימוש חוזר ב-handlers, התנהגות ניסיונות חוזרים ותיעוד — כל אלה הופכים לאחריותכם. הייתי ממליץ על זה רק כששתי האפשרויות הראשונות באמת לא מתאימות.
השוואה בין שלוש הגישות
| גישה | מורכבות | גרסת .NET | בטיחות תהליכונים | תקורה |
|---|---|---|---|---|
| לקוחות בעלי שם (IHttpClientFactory) | נמוכה | .NET Core 2.1+ | גבוהה (תצורה בלתי משתנה) | נמוכה |
| SocketsHttpHandler + PooledConnectionLifetime | בינונית | .NET 6+ | גבוהה | נמוכה |
| DelegatingHandler מותאם | גבוהה | כל גרסה | תלוי במימוש | בינונית |
לרוב הצוותים, לקוחות בעלי שם הם נקודת ההתחלה הנכונה. עברו ל-PooledConnectionLifetime עבור שערי רוטציה יציבים, ולניתוב מותאם רק כשבחירת ה-proxy תלויה במטא-נתונים ברמת הבקשה.
בחירת פרוטוקול ה-proxy הנכון: HTTP, HTTPS ו-SOCKS5
לא כל ה-proxy מדברים באותה שפה, ושימוש בסכמת פרוטוקול שגויה יזכה אתכם בשגיאות מבלבלות.
HTTP proxy: מבין בקשות HTTP. עבור יעדי HTTP רגילים, הוא יכול להעביר בקשות ישירות. עבור יעדי HTTPS, הלקוח שולח בקשת CONNECT כדי ליצור מנהרה, ואז ה-TLS נסגר דרך המנהרה הזו מול היעד. זהו המודל הנפוץ ביותר.
proxy עם סיום HTTPS (HTTPS-terminating): ה-proxy מציג תעודת TLS משלו ומצפין מחדש את התעבורה במעלה הזרם. נפוץ במערכות בדיקה ארגוניות ובחלק מ-API ה-scraping המנוהלים. יכול לגרום לשגיאות אימות תעודה אם הלקוח לא סומך על שרשרת התעודות של ה-proxy.
SOCKS5 proxy: מנהרת TCP בשכבת התעבורה שעובדת עבור כל תעבורת TCP, לא רק HTTP. בשימוש נרחב אצל ספקי residential proxy. נתמך באופן טבעי ב-.NET 6+.
דוגמת SOCKS5:
var handler = new SocketsHttpHandler
{
Proxy = new WebProxy("socks5://proxy.example.com:1080")
{
Credentials = new NetworkCredential("proxy-user", "proxy-password")
},
UseProxy = true
};
using var client = new HttpClient(handler);
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine(ip);
הערה על אימות תעודות SSL
בשימוש ב-proxy מסוג HTTPS-terminating, אתם עלולים לראות שגיאות RemoteCertificateNameMismatch. באמצעות ServerCertificateCustomValidationCallback אפשר להתאים אישית את האימות:
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
השתמשו בזה רק בפיתוח מקומי או מול proxy מיירט-TLS מהימן ומאושר. החזרת true בעיוורון מנטרלת בדיקת אבטחה קריטית וחושפת אתכם להתקפות man-in-the-middle. בפרודקשן עם proxy סטנדרטי מסוג CONNECT או SOCKS, השאירו את אימות ה-SSL פעיל.
פתרון שגיאות proxy נפוצות ב-HttpClient של C#

הטבלה הזו ממפה את התסמין הגלוי לשורש הבעיה הסביר ולתיקון הראשון שכדאי לנסות. הייתי שומר את הפרק הזה במועדפים — הוא מכסה את השגיאות שמופיעות הכי הרבה ב-שרשורי Stack Overflow ובפורומי מפתחים.
| שגיאה / תסמין | סיבה נפוצה | תיקון |
|---|---|---|
| 407 Proxy Authentication Required | פרטי הזדהות הוגדרו על handler.Credentials במקום על handler.Proxy.Credentials; פורמט שם משתמש שגוי; תווים מיוחדים בסיסמה המוטמעת ב-URL | השתמשו ב-WebProxy.Credentials = new NetworkCredential(...); הימנעו מהטמעת פרטי הזדהות ב-URI; ודאו את פורמט שם המשתמש של הספק |
| TaskCanceledException / Timeout | נקודת קצה של proxy איטית, לא זמינה, עמוסה או חסומה בחומת אש; ברירת המחדל של 100 שניות קצרה מדי | בדקו את ה-proxy עם curl; הגדילו את HttpClient.Timeout רק אחרי שהוכחתם שנקודת הקצה עובדת; הוסיפו ניסיונות חוזרים ובדיקות תקינות ל-proxy |
| SocketException / מיצוי סוקטים | יצירה והשמדה של HttpClient או של handlers בכל בקשה | השתמשו ב-IHttpClientFactory, בלקוחות singleton, או ב-SocketsHttpHandler עם בקרות pooling |
| SSL RemoteCertificateNameMismatch | יירוט HTTPS על ידי proxy ארגוני או מנוהל | התקינו/סמכו על ה-CA של ה-proxy כשמתאים; השתמשו באימות מותאם רק בסביבת פיתוח מבוקרת או בתרחישי MITM מאושרים |
| לולאת הפניות 302 | דף שבוי (captive page) של proxy/VPN ארגוני או חסימת רשימת היתר שמפנה שוב ושוב | בדקו חיבור ישיר; בחנו את כותרות Location; בדקו את רשימת ההיתר של ה-proxy ואת פורטל האימות |
| HttpRequestException / אין חיבור עם כתובת SOCKS | הרצת קוד SOCKS על .NET Framework או על .NET ישן; סכמה או פורט שגויים | השתמשו ב-.NET 6+ לתמיכת SOCKS מובנית; ודאו socks5://host:port; בדקו מול תיעוד הספק |
| נראה שה-proxy מתעלמים ממנו | UseProxy = false; היעד נחשב מקומי ולכן נעקף; משתנה הסביבה NO_PROXY; ה-handler מוגדר אחרת ממה שציפיתם | הגדירו UseProxy = true; בדקו את HttpClient.DefaultProxy; נקו או דרסו משתני סביבה; הגדירו BypassProxyOnLocal = false |
תהליך דיבוג מהיר
- האם הבקשה הצליחה? ← כן: השוו את הפלט של
api.ipify.orgל-IP הצפוי של ה-proxy. - לא, יש קוד סטטוס HTTP? ← 407: תקנו את פרטי ההזדהות של ה-proxy. 403/429: היעד חסם או הגביל בקצב את ה-proxy. לולאת 3xx: ייתכן שה-proxy או השער הארגוני מבצעים הפניה.
- אין קוד סטטוס, רק חריגה? ← Timeout: בדקו את זמינות ה-proxy. חריגת socket/תעודה: בדקו pooling, פרוטוקול, TLS וגרסת .NET.
פקודות ראשונות שימושיות לאימות ה-proxy עצמו, מחוץ ל-.NET:
curl -x http://user:pass@proxy.example.com:8080 https://api.ipify.org/
curl --socks5 user:pass@proxy.example.com:1080 https://api.ipify.org/
אם curl עובד אבל הקוד שלכם ב-C# לא, ההבדל הוא בדרך כלל בסכמת האימות, במאגר תעודות ה-TLS, במשתני סביבה או ב-escaping של פרטי ההזדהות. התאימו במדויק את כתובת ה-proxy, הסכמה והאימות של curl, ואז העבירו את פרטי ההזדהות ל-NetworkCredential.
מתי לוותר על ניהול proxy: החלופה ללא קוד
חלק משמעותי מהמפתחים שמחפשים "HttpClient proxy C#" לא באמת מנסים ללמוד תיאוריית proxy — הם מנסים לשמור על scraper שממשיך לרוץ. שווה להיות כנים לגבי מתי קוד proxy מותאם ב-C# הוא הכלי הנכון, ומתי לא.
בנו scraper מותאם ב-C# עם רוטציית proxy כאשר:
- אתם צריכים שליטה מלאה בלוגיקת הבקשות, ב-cookies, בכותרות, בניסיונות החוזרים ובפענוח
- ה-scraper משתלב בבסיס קוד .NET קיים או בשירות פנימי
- דרישות ציות או אבטחה מחייבות שהתשתית תהיה בבעלותכם מקצה לקצה
השתמשו בכלי ללא קוד כמו Thunderbit כאשר:
- המטרה היא חילוץ נתונים מובנים מאתרים, ולא תשתית HTTP
- אתם מעדיפים לא לתחזק מאגרי proxy, לא לטפל ב-CAPTCHA ולא לדבג מיצוי סוקטים
- הצוות צריך נתונים ב-Excel, Google Sheets, Airtable או Notion בלי לכתוב קוד פענוח
תוסף ה-Chrome של Thunderbit מטפל ברוטציית proxy ובאמצעי anti-bot באופן אוטומטי, דרך אפשרות ה-scraping בענן. ה-API שלו מאפשר למפתחים להגדיר סכמת JSON ולקבל בחזרה נתונים מובנים, בלי לנהל בכלל HttpClient או WebProxy. לצוותים שעוסקים ב-web scraping להשוואת מחירים או ב-חילוץ לידים, הפער בזמן ההקמה הוא משמעותי.
| תרחיש | C# מותאם + proxy | Thunderbit |
|---|---|---|
| שליטה מלאה בלוגיקת הבקשות | כן | לא (שליטה ברמת API) |
| נדרש ניהול proxy | כן | לא (מטופל אוטומטית) |
| טיפול ב-anti-bot / CAPTCHA | ידני או צד שלישי | מובנה |
| זמן הקמה | שעות עד ימים | דקות |
| מתאים במיוחד ל | בסיסי קוד .NET קיימים, צינורות מותאמים | חילוץ נתונים מהיר, צוותים לא-טכניים, ייצוא לגיליונות |
זו לא טענה בסגנון "לעולם אל תשתמשו ב-HttpClient". אם אתם בונים שירות .NET לפרודקשן, אתם בהחלט צריכים להבין הגדרות proxy. אבל אם אתם מבזבזים שעות על דיבוג שגיאות 407 עבור משימת איסוף נתונים חד-פעמית — קיימות אפשרויות פשוטות יותר, ואין שום בושה להשתמש בהן. אתם יכולים לעיין ב-תוכניות התמחור של Thunderbit או לבדוק את ערוץ ה-YouTube להדגמות.
נקודות מפתח
הדפוס הבסיסי נשאר זהה: WebProxy ← handler ← HttpClient. כל השאר עוסק בהתחמקות מטעויות תפעוליות שצפות בפרודקשן.
- פרטי ההזדהות הולכים על ה-proxy, לא על ה-handler. קטע הקוד ההשוואתי בפרק ה-407 הוא הדבר הכי חשוב לזכור.
- אל תיצרו
HttpClientחדש לכל בקשה או לכל proxy. השתמשו ב-IHttpClientFactoryללקוחות בעלי שם, ב-SocketsHttpHandlerעםPooledConnectionLifetimeלשערי רוטציה, או ב-handler ניתוב מותאם לתרחישים מתקדמים. - בדקו את גרסת ה-.NET שלכם לפני שאתם מעתיקים קוד SOCKS5 או
SocketsHttpHandler. מטריצת התאימות שלמעלה תחסוך מכם כשלים שקטים. - בדקו את ה-proxy קודם מחוץ ל-.NET. פקודת
curlמהירה מחסלת קטגוריה שלמה של דיבוג. - לחילוץ נתונים מובנים בלי כאבי ראש של proxy, כלים כמו Thunderbit מטפלים בשכבת התעבורה כדי שתוכלו להתמקד בנתונים עצמם.
בפעם הבאה שתיתקלו ב-407 או ב-TaskCanceledException, התחילו מטבלת פתרון התקלות שלמעלה.
שאלות נפוצות
האם אפשר להחליף את ה-proxy על מופע HttpClient קיים?
לא. ה-proxy קשור ל-handler, וה-handler נקבע בזמן הבנייה. HttpClient לא חושף מאפיין Proxy שניתן לשינוי. עבור proxy שונים, צרו handlers ולקוחות נפרדים, ונהלו אותם באמצעות לקוחות בעלי שם של IHttpClientFactory או מאגר של לקוחות מוגדרים מראש.
האם HttpClient משתמש ב-proxy של המערכת כברירת מחדל?
כן. ב-.NET המודרני, אם לא תגדירו handler במפורש, HttpClient יורש את הגדרות ה-proxy שברירת המחדל של המערכת — כולל משתני סביבה כמו HTTPS_PROXY ו-HTTP_PROXY דרך HttpClient.DefaultProxy. כדי לבטל זאת, הגדירו במפורש UseProxy = false על ה-handler.
איך משתמשים ב-SOCKS5 proxy עם HttpClient ב-C#?
השתמשו ב-new WebProxy("socks5://host:port") יחד עם SocketsHttpHandler. תמיכה מובנית ב-SOCKS proxy דורשת .NET 6 ומעלה. ב-.NET Framework 4.x אין תמיכה מובנית ב-SOCKS5 — תצטרכו ספרייה של צד שלישי.
למה אני ממשיך לקבל 407 Proxy Authentication Required?
סביר להניח שאתם מגדירים את פרטי ההזדהות על handler.Credentials (שמכוון לשרת היעד) במקום על handler.Proxy.Credentials (שמכוון ל-proxy). ראו את הפרק "פרטי הזדהות של proxy מול פרטי הזדהות של שרת" שלמעלה לדפוס הנכון.
האם בטוח לבטל אימות תעודות SSL בעבודה עם proxy?
רק בפיתוח מקומי או כשאתם סומכים על ספק ה-proxy באופן מוחלט (למשל, API scraping מנוהל במצב HTTPS proxy). בפרודקשן עם proxy סטנדרטי מסוג CONNECT או SOCKS, השאירו את אימות ה-SSL פעיל כדי למנוע התקפות man-in-the-middle.
נסו את Thunderbit ל-web scraping ללא מאמץ Get Started Free
למידע נוסף


