الأسبوع الماضي قضيت وقتًا طويلًا ومحرجًا وأنا أحدّق في ردّ 407 Proxy Authentication Required وأنا مقتنع أن مزوّد البروكسي عندي فيه مشكلة. وفي النهاية اتضح أنني وضعت بيانات الاعتماد في الخاصية الغلط — إصلاح من سطرين أخذ مني ساعتين حتى أكتشفه. إذا كان هذا السيناريو مألوفًا لك، فهذا الدليل لك.
إعداد البروكسي مع HttpClient في C# من المواضيع التي تبدو بسيطة على الورق، لكن التفاصيل في بيئة الإنتاج — مثل استنزاف المقابس، وعدم تطابق إصدار SOCKS5، واللخبطة في بيانات الاعتماد — تسرق وقتًا حقيقيًا.
أنا أعمل على أدوات كشط الويب واستخراج البيانات في Thunderbit منذ فترة، وشفت الأخطاء نفسها تتكرر كثيرًا، سواء في النقاشات الهندسية الداخلية أو في مجتمعات المطورين التي نتابعها. هذا الشرح يغطي المسار الكامل: الإعداد، المصادقة، تدوير البروكسي، اختيار البروتوكول، وجدول استكشاف الأخطاء الذي كنت أتمنى لو وجدته من أول يوم.
مستوى الصعوبة: مبتدئ إلى متوسط
الوقت المطلوب: حوالي 15 دقيقة للمتابعة، وأكثر إذا كنت ستطبّق أنماط التدوير في بيئة إنتاج
ما ستحتاجه: .NET 6+ SDK (لدعم SOCKS5 وميزات الـ handler الحديثة؛ كما يعمل .NET Framework 4.x لأمثلة بروكسي HTTP الأساسية)، ومحرر كود، ونقطة بروكسي واحدة على الأقل للاختبار
ما هو HttpClient ولماذا يحتاج إلى بروكسي؟

HttpClient هو الصنف المدمج في .NET داخل System.Net.Http لإرسال طلبات HTTP واستقبال الردود. وهو يدعم async/await، والرؤوس المخصصة، وCancellationToken، والإعداد عبر الـ handlers. وتصفه Microsoft بأنه صنف لإرسال طلبات HTTP واستقبال استجابات HTTP من مورد محدد بواسطة URI.
خادم البروكسي هو وسيط بين تطبيقك والموقع المستهدف. عندما تمرّر الحركة عبر بروكسي، يرى الموقع عنوان IP الخاص بالبروكسي بدلًا من عنوانك.
HttpClient نفسه لا يملك خاصية Proxy. إعداد التوجيه عبر البروكسي يتم على الـ handler الأساسي — إما HttpClientHandler أو SocketsHttpHandler — والذي يقبل كائنًا من WebProxy. النموذج الذهني يكون كالتالي:
[تطبيق C# الخاص بك] → [HttpClient + Handler] → [خادم البروكسي] → [الموقع المستهدف]
لذلك، فكرة “تغيير البروكسي على HttpClient مباشرة” ليست مجرد تعيين خاصية، بل هي مسألة تصميم كاملة. سنفصل أكثر في جزء التدوير.
جرّب Thunderbit لاستخراج البيانات بسهولة أكبر
لماذا تستخدم بروكسي مع HttpClient في C#؟
المطورون يوجّهون حركة HttpClient عبر البروكسيات لأسباب متكررة، ونوع البروكسي المناسب يعتمد على المهمة نفسها.
- تجنب حظر IP وحدود المعدل: مهم جدًا لكشط الويب، وتوليد العملاء المحتملين، أو مراقبة الأسعار على نطاق واسع. أي عنوان IP واحد يهاجم موقعًا بسرعة غالبًا سيتحظر.
- تجاوز القيود الجغرافية: الوصول إلى واجهات API أو محتوى مقيد بمنطقة معينة عبر تمرير الحركة من دول محددة.
- إخفاء عنوانك الأصلي: إضافة طبقة خصوصية عند جمع البيانات الحساسة أو تنفيذ بحث تنافسي.
- متطلبات مؤسسية أو امتثالية: كثير من الشركات تشترط مرور الحركة الخارجية عبر بوابة مركزية لأغراض التسجيل والحوكمة.
- الاختبار وضمان الجودة: محاكاة طلبات من مواقع أو ظروف شبكة مختلفة من دون نشر بنية تحتية فعلية في تلك المناطق.
| حالة الاستخدام | نوع البروكسي المعتاد | لماذا يناسب |
|---|---|---|
| كشط الويب على نطاق واسع | بروكسيات سكنية متغيرة | تنوع أكبر في عناوين IP وصعوبة أعلى على أنظمة مكافحة البوت |
| مراقبة أسعار التجارة الإلكترونية | بروكسيات سكنية أو بروكسيات مراكز بيانات موجّهة جغرافيًا | فحص الأسعار والمخزون بحسب المنطقة |
| الوصول إلى API عبر بوابة ثابتة | بروكسي مراكز بيانات أو بروكسي مؤسسي | IP متوقع لإدراج السماح، وتكلفة أقل |
| الامتثال المؤسسي | بروكسي النظام، بروكسي PAC، أو بروكسي شركة بمصادقة | تسجيل مركزي وتحكم في الحركة الخارجة |
| اختبار QA والتعريب | مجموعة بروكسيات خاصة بدول معينة | محاكاة وصول المستخدمين الحقيقيين من المناطق المستهدفة |
وعادةً، استخدام البروكسي يتدرج بشكل منطقي. تبدأ ببروكسي ثابت واحد للتأكد من أن التوجيه شغال. ثم ينتقل كاشف الإنتاج إلى مجموعة بروكسيات، مع ربط الطلبات بالبروكسيات حسب النطاق المستهدف أو الموقع الجغرافي أو معدل الفشل. أما الفرق الناضجة فتتجه غالبًا إلى بوابة بروكسي مُدارة تتولى التدوير وإعادة المحاولة وثبات الجلسة خلف نقطة نهاية واحدة.
تدوير البروكسي ليس عصا سحرية. إذا كان الموقع المستهدف يحظر السلوك المشبوه، فمجرد تغيير عناوين IP لن يفيد كثيرًا إلا إذا تمت أيضًا إدارة معدل الطلبات والرؤوس والكوكيز وبصمة TLS بعناية.
ما الذي تدعمه كل نسخة من .NET: جدول توافق سريع
نسخ مقطع بروكسي من تدوينة ولصقه في إطار مستهدف غير مناسب هو من أكبر أسباب الأعطال الصامتة. أهم خط فاصل هنا هو بين .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، فالتزم ببروكسيات HTTP/HTTPS مع HttpClientHandler وWebProxy. أما SOCKS5 والتحكمات الحديثة في التجميع فتحتاج إلى .NET 6 أو أحدث.
في نقطة مهمة جدًا: HttpClient.DefaultProxy خاصية ثابتة في .NET الحديث. إذا تم ضبطها في كود بدء التشغيل المشترك أو ورثتها من متغيرات البيئة مثل HTTPS_PROXY أو HTTP_PROXY, فكل كائن HttpClient سيستخدمها ما لم تلغها صراحةً على مستوى الـ handler. وفي بيئات الحاويات، هذا سبب شائع جدًا لحالة “ليش العميل يستخدم بروكسي أنا أصلًا ما ضبطته؟”.
الخطوة 1: أنشئ مشروع Console جديدًا بـ C#
افتح الطرفية وأنشئ مشروعًا جديدًا:
dotnet new console -n ProxyHttpClientDemo
cd ProxyHttpClientDemo
تحقق من إصدار الـ SDK عبر dotnet --version. الأمثلة في هذا الدليل تستهدف .NET 6+ لتغطية كامل الميزات. إذا كنت تريد أحدث إصدار LTS، فحمّله من صفحة تنزيل Microsoft.
افتح Program.cs في محررك. هناك سيبدأ كل شيء.
الخطوة 2: نفّذ طلب HTTP أساسيًا بدون بروكسي
قبل إعداد البروكسي، حدّد عنوان IP الحقيقي الخارج من شبكتك. بهذه الطريقة، بعد تفعيل البروكسي، تقدر تتأكد أن الـ 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 بنقطة نهاية البروكسي الفعلية عندك. إذا كان كل شيء مضبوطًا صح، يجب أن يطابق عنوان IP الناتج عنوان الخروج الخاص بالبروكسي، وليس عنوانك الحقيقي.
الخصائص الأساسية التي لازم تفهمها:
Proxy— كائنIWebProxyالذي يستخدمه الـ handler للتوجيه.UseProxy = true— يخبر الـ handler أن يستخدم البروكسي المهيأ فعلًا. (ممكن يبدو بديهيًا، لكن نسيانه يضيع وقتًا طويلًا جدًا.)BypassProxyOnLocal = false— يمنع الـ handler من تجاوز البروكسي للوجهات التي تبدو “محلية”.UseDefaultCredentials— يتحكم فيما إذا كان الـ handler يرسل بيانات اعتماد Windows الافتراضية. وهذا ليس نفسه اسم المستخدم/كلمة المرور الخاصة بالبروكسي.

الخطوة 4: أضف مصادقة البروكسي باستخدام NetworkCredential
كثير من مزوّدي البروكسي المدفوع يطلبون بيانات اعتماد. النمط الصحيح هو ضبطها على كائن 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. هذا يتفادى مشاكل الهروب مع المحارف الخاصة في كلمات المرور، ويخلي الفرق بين الـ URI وبيانات الاعتماد واضحًا.
سأشرح أكثر خطأ المصادقة الشائع — ولماذا يسبب أخطاء 407 — في قسم مخصص أدناه.
الخطوة 5: صدّر أو استخدم بيانات الاستجابة
في أي شيء يتجاوز فحص IP سريعًا، تعامل مع الاستجابة بشكل صحيح:
using var response = await client.GetAsync("https://example.com/api/products");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine($"فشل الطلب: {(int)response.StatusCode} {response.ReasonPhrase}");
return;
}
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
في تدفقات الكشط، الطلب عبر البروكسي هو فقط طبقة النقل. ما زلت بحاجة إلى التحليل، والتطبيع، وإزالة التكرار، وإعادة المحاولة، والتصدير إلى Excel أو Google Sheets أو قواعد البيانات أو وجهات أخرى. أدوات مثل Thunderbit يمكنها أتمتة خطوات الاستخراج والتصدير — إذ يتولى امتداد Chrome استخراج البيانات المهيكلة والتصدير المجاني إلى Google Sheets أو Excel أو Airtable أو Notion من دون الحاجة إلى كتابة كود تحليل.
صدّر البيانات المستخرجة إلى Excel أو Sheets أو Airtable أو Notion Get Started Free
بيانات اعتماد البروكسي مقابل بيانات اعتماد الخادم: الخطأ الذي يسبب أخطاء 407

شفت هذا الخطأ في نقاشات Stack Overflow، وفي منشورات Microsoft Q&A، وبصراحة في كودي أنا أيضًا.
الفرق بسيط لكنه سهل الالتباس:
- بيانات اعتماد البروكسي تصادقك لدى خادم البروكسي نفسه.
- بيانات اعتماد الخادم تصادقك لدى الخادم/الوجهة النهائية.
في HttpClientHandler، يوجد كل نوع على خاصية مختلفة. وضع بيانات الاعتماد في المكان الخطأ هو السبب رقم 1 لأخطاء 407 Proxy Authentication Required.
// ❌ خطأ — يضبط بيانات اعتماد الخادم المستهدف، وليس البروكسي
handler.Credentials = new NetworkCredential("user", "pass");
// ✅ صحيح — يضبط بيانات الاعتماد على كائن البروكسي نفسه
handler.Proxy = new WebProxy("http://proxy:8080")
{
Credentials = new NetworkCredential("user", "pass")
};
HttpClientHandler.Credentials تخص الوجهة النهائية. أما WebProxy.Credentials فتخص البروكسي. إذا رجّع البروكسي الخطأ 407، فبيانات الاعتماد لازم تكون على البروكسي.
فخ ثاني: HttpClientHandler.PreAuthenticate يتحكم بسلوك المصادقة المسبقة لمصادقة الخادم الهدف. وهو لا يتحكم في رأس Proxy-Authorization. لا تستخدمه كحل لمشكلة 407.
كيفية تدوير البروكسي مع HttpClient في C#
المطورون يسألون عن هذا باستمرار في المنتديات. والإجابة الأولى شوي محبطة: لا يمكنك تغيير البروكسي على كائن HttpClient وهو شغال. البروكسي يعيش على الـ handler. والـ handler يُعيَّن وقت الإنشاء. وHttpClient ما عنده خاصية Proxy قابلة للتعديل.
الحل الساذج — new HttpClient(new HttpClientHandler { Proxy = ... }) لكل طلب — يخلق مشكلة ثانية. Microsoft تحذر بوضوح من أن إنشاء العملاء والتخلص منهم لكل طلب قد يستنزف منافذ TCP المتاحة لأن المنافذ لا تتحرر فورًا بعد إغلاق الاتصال.

لذلك، هذه ثلاثة أنماط عملية في بيئة الإنتاج تعمل فعلًا.
الخيار 1: عملاء مسمّون عبر IHttpClientFactory
إذا كانت مجموعة البروكسيات معروفة عند بدء التشغيل، فالعملاء المسمّون Named Clients هو الخيار الأقل تعقيدًا. كل عميل مسمى يحصل على إعداد 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 ويتفادى نمط إنشاء عميل جديد لكل طلب.
الخيار 2: SocketsHttpHandler + PooledConnectionLifetime (.NET 6+)
لعميل طويل العمر خلف بوابة بروكسي يتغير عنوان الخروج عند الاتصالات الجديدة، فإن 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 سحريًا لكل طلب. لكنه يعمل بشكل ممتاز مع بوابات البروكسي التي تمنح عنوان IP مختلفًا لكل اتصال TCP جديد، أو مع مجموعات بروكسي تعتمد على DNS حيث يشير الاسم إلى نقاط نهاية مختلفة مع الوقت.
الخيار 3: DelegatingHandler مخصص لاختيار البروكسي المتقدم
عندما يعتمد اختيار البروكسي على عنوان الطلب أو الحمولة أو سياق التشغيل، يمكن لـ 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);
}
}
هذا تصميم متقدم. ستصبح مسؤولًا عن سلامة التزامن، والتخلص من الكائنات، وإعادة استخدام الـ handlers، وسلوك إعادة المحاولة، والتسجيل. أوصي به فقط عندما لا تناسبك الخيارات الأولى فعلًا.
مقارنة بين الطرق الثلاث
| النهج | التعقيد | إصدار .NET | أمان الخيوط | الحمل الإضافي |
|---|---|---|---|---|
| العملاء المسمّون (IHttpClientFactory) | منخفض | .NET Core 2.1+ | مرتفع (تهيئة غير قابلة للتغيير) | منخفض |
| SocketsHttpHandler + PooledConnectionLifetime | متوسط | .NET 6+ | مرتفع | منخفض |
| DelegatingHandler مخصص | مرتفع | أي إصدار | يعتمد على التنفيذ | متوسط |
بالنسبة لمعظم الفرق، العملاء المسمّون هم نقطة البداية الصحيحة. انتقل إلى PooledConnectionLifetime للبوابات المتغيرة المستقرة، واستخدم التوجيه المخصص فقط عندما يعتمد اختيار البروكسي على بيانات على مستوى الطلب.
اختيار بروتوكول البروكسي المناسب: HTTP وHTTPS وSOCKS5
ليست كل البروكسيات تتحدث اللغة نفسها، واستخدام مخطط البروتوكول الخطأ سيعطيك أخطاء مربكة.
بروكسي HTTP: يفهم طلبات HTTP. مع الوجهات HTTP العادية، يمكنه تمرير الطلب مباشرة. أما مع الوجهات HTTPS، فيرسل العميل طلب CONNECT لإنشاء نفق، ثم يتم التفاوض على TLS عبر هذا النفق مع الوجهة. هذا هو النموذج الأكثر شيوعًا.
بروكسي ينهي HTTPS: يقدم البروكسي شهادته TLS الخاصة، ثم يعيد تشفير الحركة الصادرة. هذا شائع في أنظمة الفحص المؤسسي وبعض واجهات scraping المدارة. وقد يسبب أخطاء تحقق من الشهادة إذا كان العميل لا يثق بسلسلة شهادات البروكسي.
بروكسي SOCKS5: نفق TCP على طبقة النقل يعمل مع أي حركة TCP، وليس HTTP فقط. ويُستخدم كثيرًا لدى مزودي البروكسي السكني. مدعوم محليًا في .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
عند استخدام بروكسيات تنهي HTTPS، قد ترى أخطاء RemoteCertificateNameMismatch. يمكن لـ ServerCertificateCustomValidationCallback تخصيص التحقق:
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
استخدم هذا فقط في التطوير المحلي أو مع بروكسي TLS-intercepting موثوق ومعتمد. إرجاع true بشكل أعمى يلغي فحصًا أمنيًا مهمًا جدًا ويعرضك لهجمات الرجل في المنتصف. في الإنتاج مع بروكسيات CONNECT أو SOCKS القياسية، أبقِ التحقق من SSL مفعّلًا.
استكشاف أخطاء البروكسي الشائعة في C# HttpClient

هذا الجدول يربط العرض الظاهر بالسبب الأرجح وأول إصلاح ينبغي تجربته. أنصحك بوضع إشارة مرجعية على هذا القسم — لأنه يغطي الأخطاء التي تظهر كثيرًا في نقاشات Stack Overflow ومنتديات المطورين.
| الخطأ / العَرَض | السبب الشائع | الحل |
|---|---|---|
| 407 Proxy Authentication Required | وُضعت بيانات الاعتماد على handler.Credentials بدلًا من handler.Proxy.Credentials؛ أو صيغة اسم المستخدم خاطئة؛ أو توجد محارف خاصة داخل كلمة المرور المضمّنة في URL | استخدم WebProxy.Credentials = new NetworkCredential(...); وتجنّب تضمين البيانات داخل URI; وتحقق من صيغة اسم المستخدم لدى المزوّد |
| TaskCanceledException / Timeout | نقطة نهاية البروكسي بطيئة أو غير قابلة للوصول أو مثقلة أو محجوبة بجدار ناري؛ أو مهلة 100 ثانية الافتراضية قصيرة جدًا | اختبر البروكسي باستخدام curl; وزد HttpClient.Timeout فقط بعد التأكد من أن النقطة تعمل؛ وأضف إعادة المحاولة وفحوصات صحة البروكسي |
| SocketException / استنزاف المقابس | إنشاء HttpClient أو handlers والتخلص منها لكل طلب | استخدم IHttpClientFactory أو عملاء singleton أو SocketsHttpHandler مع ضوابط التجميع |
| SSL RemoteCertificateNameMismatch | اعتراض HTTPS بواسطة بروكسي مؤسسي أو مُدار | ثبّت/ثق CA الخاص بالبروكسي عند الحاجة؛ واستخدم التحقق المخصص فقط في بيئات تطوير مضبوطة أو سيناريوهات MITM المعتمدة |
| حلقة إعادة توجيه 302 | صفحة captive portal على بروكسي/ VPN أو حظر allowlist يعيد التوجيه مرارًا | اختبر الاتصال المباشر؛ وافحص رؤوس Location; وتحقق من allowlist و بوابة المصادقة |
| HttpRequestException / لا يوجد اتصال مع عنوان SOCKS | تشغيل كود SOCKS على .NET Framework أو إصدار أقدم؛ أو استخدام scheme أو port خاطئ | استخدم .NET 6+ للدعم المحلي لـ SOCKS؛ وتحقق من socks5://host:port; واختبر مع توثيق المزوّد |
| البروكسي يبدو وكأنه يتم تجاهله | UseProxy = false; أو تم تجاوز الوجهة باعتبارها محلية؛ أو متغير البيئة NO_PROXY; أو أن الـ handler مهيأ بشكل مختلف عما تتوقع | اضبط UseProxy = true; وافحص HttpClient.DefaultProxy; وامسح أو تجاوز متغيرات البيئة؛ واضبط BypassProxyOnLocal = false |
مسار سريع للتشخيص
- هل نجح الطلب؟ → نعم: قارن ناتج
api.ipify.orgمع عنوان IP المتوقع للبروكسي. - لا، هناك رمز حالة HTTP؟ → 407: أصلح بيانات اعتماد البروكسي. 403/429: الموقع حظر البروكسي أو فرض حدًا للمعدل. حلقة 3xx: قد تكون البوابة المؤسسية/البروكسي تعيد التوجيه.
- لا يوجد رمز حالة، فقط استثناء؟ → Timeout: اختبر قابلية الوصول للبروكسي. استثناء Socket/الشهادة: افحص التجميع، والبروتوكول، وTLS، وإصدار .NET.
أوامر سريعة مفيدة للتحقق من البروكسي خارج .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، أو متغيرات البيئة، أو هروب المحارف في بيانات الاعتماد. طابق عنوان البروكسي والمخطط وآلية المصادقة في curl تمامًا، ثم انقل بيانات الاعتماد إلى NetworkCredential.
متى تتجاوز إدارة البروكسي: البديل بدون كود
جزء معتبر من المطورين الذين يبحثون عن “HttpClient proxy C#” لا يحاولون تعلم نظرية البروكسي، بل يحاولون فقط إبقاء كاشف يعمل. ومن المفيد أن نكون صريحين بشأن متى يكون كود C# المخصص هو الأداة الصحيحة ومتى لا يكون كذلك.
ابنِ كاشف C# مخصصًا مع تدوير البروكسي عندما:
- تحتاج تحكمًا كاملًا في منطق الطلبات والكوكيز والرؤوس وإعادة المحاولة والتحليل
- يتكامل الكاشف مع قاعدة كود .NET موجودة أو خدمة داخلية
- تتطلب متطلبات الامتثال أو الأمان أن تمتلك البنية من البداية إلى النهاية
استخدم أداة بدون كود مثل Thunderbit عندما:
- يكون الهدف استخراج بيانات منظمة من المواقع، وليس بناء بنية HTTP
- لا تريد صيانة مجموعات البروكسي أو التعامل مع CAPTCHA أو إصلاح استنزاف المقابس
- يحتاج الفريق إلى البيانات في Excel أو Google Sheets أو Airtable أو Notion من دون كتابة كود تحليل
يتولى امتداد Chrome الخاص بـ Thunderbit تدوير البروكسي والتعامل مع إجراءات مكافحة البوت تلقائيًا عبر خيار الكشط السحابي. كما تتيح واجهته البرمجية للمطورين تعريف مخطط JSON والحصول على بيانات منظمة من دون إدارة HttpClient أو WebProxy أصلًا. بالنسبة للفرق التي تعمل على كشط الويب لمقارنة الأسعار أو استخراج العملاء المحتملين، فإن فرق وقت الإعداد كبير جدًا.
| السيناريو | C# مخصص + بروكسي | Thunderbit |
|---|---|---|
| تحكم كامل في منطق الطلبات | نعم | لا (تحكم على مستوى API فقط) |
| الحاجة لإدارة البروكسي | نعم | لا (مدار تلقائيًا) |
| التعامل مع Anti-bot / CAPTCHA | يدوي أو عبر طرف ثالث | مدمج |
| وقت الإعداد | من ساعات إلى أيام | دقائق |
| الأنسب لـ | قواعد كود .NET الحالية، والـ pipelines المخصصة | استخراج سريع للبيانات، الفرق غير التقنية، والتصدير إلى الجداول |
هذا ليس دعوة لعدم استخدام HttpClient أبدًا. إذا كنت تبني خدمة .NET في بيئة إنتاج، فعليك فعلًا فهم إعداد البروكسي. لكن إذا كنت تقضي ساعات في تصحيح أخطاء 407 لمهمة جمع بيانات لمرة واحدة، فهناك خيارات أبسط — ولا عيب في استخدامها. يمكنك استكشاف أسعار Thunderbit أو زيارة قناة YouTube للاطلاع على الشروحات.
الخلاصة الأساسية
النمط الأساسي يظل نفسه: WebProxy → handler → HttpClient. وكل ما بعد ذلك يتعلق بتجنب الأخطاء التشغيلية التي تظهر في الإنتاج.
- ضع بيانات الاعتماد على البروكسي، لا على الـ handler. المقتطفان جنبًا إلى جنب في قسم 407 هما أهم شيء لازم تتذكره.
- لا تنشئ
HttpClientجديدًا لكل طلب أو لكل بروكسي. استخدمIHttpClientFactoryللعملاء المسمّين، أوSocketsHttpHandlerمعPooledConnectionLifetimeلبوابات التدوير، أو handler توجيه مخصص للسيناريوهات المتقدمة. - تحقق من إصدار .NET قبل نسخ كود SOCKS5 أو
SocketsHttpHandler. جدول التوافق أعلاه يجنبك الأعطال الصامتة. - اختبر البروكسي خارج .NET أولًا. أمر
curlسريع يزيل فئة كاملة من التشخيص. - لاستخراج البيانات المنظمة من دون صداع البروكسي، أدوات مثل Thunderbit تتولى طبقة النقل لتتمكن من التركيز على البيانات نفسها.
في المرة القادمة التي تصطدم فيها بـ 407 أو TaskCanceledException، ابدأ بجدول استكشاف الأخطاء أعلاه.
الأسئلة الشائعة
هل يمكنني تغيير البروكسي على مثيل HttpClient موجود بالفعل؟
لا. البروكسي مرتبط بالـ handler، والـ handler يُضبط وقت الإنشاء. HttpClient لا يوفّر خاصية Proxy قابلة للتغيير. إذا أردت بروكسيات مختلفة، فأنشئ handlers وعملاء منفصلين، وأدرهم عبر عملاء مسمّين من IHttpClientFactory أو مجموعة من العملاء المهيئين مسبقًا.
هل يستخدم HttpClient بروكسي النظام افتراضيًا؟
نعم. في .NET الحديث، إذا لم تضبط handler صراحةً، فإن HttpClient يرث إعدادات البروكسي الافتراضية للنظام — بما في ذلك متغيرات البيئة مثل HTTPS_PROXY وHTTP_PROXY عبر HttpClient.DefaultProxy. ولإلغاء ذلك، اضبط UseProxy = false صراحةً على الـ handler.
كيف أستخدم بروكسي SOCKS5 مع HttpClient في C#؟
استخدم new WebProxy("socks5://host:port") مع SocketsHttpHandler. الدعم المحلي لبروكسي SOCKS يتطلب .NET 6 أو أحدث. أما في .NET Framework 4.x، فـ SOCKS5 غير مدعوم محليًا — وستحتاج إلى مكتبة طرف ثالث.
لماذا أستمر في الحصول على 407 Proxy Authentication Required؟
على الأغلب لأنك تضع بيانات الاعتماد على handler.Credentials (الموجّهة إلى الخادم النهائي) بدلًا من handler.Proxy.Credentials (الموجّهة إلى البروكسي). راجع قسم “بيانات اعتماد البروكسي مقابل بيانات اعتماد الخادم” أعلاه لمعرفة النمط الصحيح.
هل من الآمن تعطيل التحقق من شهادة SSL عند استخدام بروكسي؟
فقط في التطوير المحلي أو عندما تثق تمامًا في مزوّد البروكسي (مثل API كشط مُدارة تعمل بوضع HTTPS proxy). في الإنتاج مع بروكسيات CONNECT أو SOCKS القياسية، أبقِ التحقق من SSL مفعّلًا لمنع هجمات الرجل في المنتصف.
جرّب Thunderbit لكشط الويب بسهولة Get Started Free
اعرف المزيد


