This example was extracted from AGPA — my fully autonomous general-purpose agent (closed-source, ~150k LOC).
A high-performance .NET library for intelligent proxy management with automatic discovery, health monitoring, and smart rotation. Built for reliable web scraping and HTTP requests, ProxyPool automatically finds working proxies from public sources, tests them in parallel, tracks their reliability, and seamlessly rotates through the healthiest options—all with zero configuration required.
Perfect for bypassing rate limits, avoiding IP blocks, and ensuring continuous access to web resources.
- Automatic Proxy Discovery: Fetches and parses proxy lists from multiple URLs
- Intelligent Health Checking: Continuously monitors proxy health and reliability
- Smart Rotation: Automatically rotates through working proxies based on reliability scores
- Parallel Testing: Tests multiple proxies concurrently for fast initialization
- Retry Logic: Built-in retry mechanism with configurable attempts
- Multiple Proxy Types: Supports HTTP, HTTPS, SOCKS4, and SOCKS5 proxies
- Authentication Support: Handles proxies with username/password authentication
- Performance Tracking: Monitors response times and reliability scores for each proxy
- Fallback Options: Optional direct connection fallback when all proxies fail
- Thread-Safe: Uses concurrent collections for safe multi-threaded access
- Easy Integration: Simple API with minimal configuration required
dotnet add package ProxyPoolgit clone https://github.com/yourusername/ProxyPool.git
cd ProxyPool
dotnet buildusing ProxyPool;
// Define proxy list sources
var proxyListUrls = new List<string>
{
"https://raw.githubusercontent.com/MuRongPIG/Proxy-Master/main/socks5.txt",
"https://raw.githubusercontent.com/monosans/proxy-list/main/proxies/socks5.txt"
};
// Create the proxy-enabled client
using var proxyClient = new ProxyEnabledHttpClient(
proxyListUrls: proxyListUrls,
testTimeoutSeconds: 10,
fetchTimeoutSeconds: 30,
maxParallelTests: 50,
maxRetries: 3,
allowDirectFallback: false
);
// Fetch content through proxies
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)).Token;
string html = await proxyClient.FetchHtmlAsync("https://example.com", cancellationToken);
Console.WriteLine($"Fetched {html.Length} characters");
// Get statistics
var stats = proxyClient.GetStatistics();
Console.WriteLine($"Healthy proxies: {stats.HealthyProxies}/{stats.TotalProxies}");using ProxyPool;
var proxyListUrls = new List<string>
{
"https://raw.githubusercontent.com/MuRongPIG/Proxy-Master/main/socks5.txt"
};
var proxyManager = new ProxyManager(
proxyListUrls: proxyListUrls,
minProxiesToFind: 10,
maxProxyTestTimeSeconds: 60
);
// Initialize the proxy pool
await proxyManager.InitializeProxyPoolAsync();
// Fetch content
string html = await proxyManager.FetchHtmlAsync("https://example.com");
Console.WriteLine($"Successfully fetched content: {html.Length} bytes");ProxyPool includes both automated tests and an interactive demo application.
Run automated tests with dotnet test or in Visual Studio Test Explorer:
dotnet testOr use the test runner scripts:
./run-tests.sh # Linux/Mac
run-tests.bat # WindowsWhat's tested:
- Proxy discovery and testing
- Statistics tracking
- Multiple request handling
- Both ProxyEnabledHttpClient and ProxyManager APIs
See ProxyPool.Tests/README.md for details.
Watch ProxyPool work in real-time with the interactive console demo:
cd ProxyPool.Demo
dotnet runOr from Visual Studio: Set ProxyPool.Demo as startup project and press F5.
The demo shows:
- âś“ Real-time proxy discovery and testing
- âś“ Detailed statistics and top proxies
- âś“ Color-coded output
- âś“ Both API styles (ProxyEnabledHttpClient and ProxyManager)
Perfect for understanding how ProxyPool works!
| Parameter | Type | Default | Description |
|---|---|---|---|
proxyListUrls |
IEnumerable<string> |
Required | URLs to fetch proxy lists from |
testTimeoutSeconds |
int |
Required | Timeout for testing individual proxies |
fetchTimeoutSeconds |
int |
Required | Timeout for fetching content through proxies |
maxParallelTests |
int |
Required | Maximum number of parallel proxy tests (1-500) |
maxRetries |
int |
3 |
Maximum retry attempts per proxy |
allowDirectFallback |
bool |
false |
Allow direct connection if all proxies fail |
userAgent |
string |
Chrome UA | Custom user agent string |
| Parameter | Type | Default | Description |
|---|---|---|---|
proxyListUrls |
List<string> |
Required | URLs to fetch proxy lists from |
minProxiesToFind |
int |
10 |
Minimum working proxies to find |
maxProxyTestTimeSeconds |
int |
60 |
Maximum time to spend testing proxies |
using var proxyClient = new ProxyEnabledHttpClient(
proxyListUrls: proxyUrls,
testTimeoutSeconds: 10,
fetchTimeoutSeconds: 30,
maxParallelTests: 50,
userAgent: "MyBot/1.0 (Custom User Agent)"
);var stats = proxyClient.GetStatistics();
Console.WriteLine($"Total Proxies: {stats.TotalProxies}");
Console.WriteLine($"Healthy Proxies: {stats.HealthyProxies}");
Console.WriteLine($"Initialized: {stats.IsInitialized}");
Console.WriteLine("\nTop Performing Proxies:");
foreach (var proxy in stats.TopProxies.Take(5))
{
Console.WriteLine($" {proxy.Address}");
Console.WriteLine($" Type: {proxy.Type}");
Console.WriteLine($" Reliability: {proxy.ReliabilityScore:P0}");
Console.WriteLine($" Success Rate: {proxy.SuccessCount}/{(proxy.SuccessCount + proxy.FailureCount)}");
Console.WriteLine($" Avg Response: {proxy.AverageResponseTime.TotalMilliseconds:F0}ms");
}using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2));
try
{
string html = await proxyClient.FetchHtmlAsync("https://example.com", cts.Token);
Console.WriteLine("Content fetched successfully");
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation timed out");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}// Allow direct connection if all proxies fail
using var proxyClient = new ProxyEnabledHttpClient(
proxyListUrls: proxyUrls,
testTimeoutSeconds: 10,
fetchTimeoutSeconds: 30,
maxParallelTests: 50,
allowDirectFallback: true // Enable fallback
);ProxyPool supports standard proxy list formats:
# Simple format
127.0.0.1:1080
192.168.1.1:8080
# With authentication
username:password@proxy.example.com:1080
# With protocol prefix
socks5://127.0.0.1:1080
http://proxy.example.com:8080
- HTTP (
http://) - HTTPS (
https://) - SOCKS4 (
socks4://) - SOCKS5 (
socks5://)
- Initialization: Fetches proxy lists from provided URLs
- Parsing: Extracts proxy addresses and credentials
- Testing: Tests proxies in parallel using test URLs
- Health Scoring: Assigns reliability scores based on success/failure
- Rotation: Automatically uses healthiest proxies first
- Monitoring: Periodic health checks update proxy status
- Retry Logic: Retries with different proxies on failure
ProxyPool uses a smart selection algorithm:
- Prioritizes proxies with high reliability scores (0.0-1.0)
- Considers average response times
- Tracks success/failure counts
- Marks proxies as unhealthy after 3 consecutive failures
- Automatically discovers new proxies when needed
Task<string> FetchHtmlAsync(string url, CancellationToken cancellationToken = default)
- Fetches HTML content from the specified URL using available proxies
- Returns: HTML content as a string, or empty string on failure
- Throws:
ArgumentExceptionif URL is invalid - Throws:
OperationCanceledExceptionif operation is cancelled
ProxyPoolStatistics GetStatistics()
- Returns current statistics about the proxy pool
- Returns:
ProxyPoolStatisticsobject with pool metrics
void Dispose()
- Cleans up resources and stops health check timer
- Always call when done using the client
Task InitializeProxyPoolAsync()
- Initializes the proxy pool by fetching and testing proxies
- Should be called before fetching content
Task<string> FetchHtmlAsync(string url)
- Simplified fetch method
- Returns: HTML content as a string
Task<ProxyEnabledHttpClient> GetProxyClientAsync()
- Returns the underlying ProxyEnabledHttpClient instance
- Returns: Configured
ProxyEnabledHttpClient
int TotalProxies: Total number of proxies in the poolint HealthyProxies: Number of currently healthy proxiesbool IsInitialized: Whether the pool has been initializedList<ProxyStatistics> TopProxies: Top 10 proxies by reliability
string Address: Proxy addressint SuccessCount: Number of successful requestsint FailureCount: Number of failed requestsdouble ReliabilityScore: Reliability score (0.0-1.0)TimeSpan AverageResponseTime: Average response timeProxyType Type: Proxy type (Http, Https, Socks4, Socks5)
- Use Multiple Proxy Sources: Provide multiple proxy list URLs for better availability
- Set Appropriate Timeouts: Balance between speed and reliability
- Monitor Health: Regularly check proxy pool statistics
- Handle Cancellation: Always use CancellationTokens for long-running operations
- Dispose Properly: Use
usingstatements or callDispose()explicitly - Start with Conservative Settings: Begin with lower
maxParallelTestsvalues - Enable Fallback Carefully: Only enable
allowDirectFallbackif direct connections are acceptable
- Verify proxy list URLs are accessible
- Increase
maxProxyTestTimeSecondsto allow more testing time - Try different proxy list sources
- Check network connectivity
- Reduce
maxParallelTeststo avoid overwhelming the system - Use faster proxy list sources
- Decrease
testTimeoutSecondsfor faster testing
- Increase
maxRetriesfor more resilience - Use
allowDirectFallbackas a safety net - Monitor proxy health with
GetStatistics() - Switch to more reliable proxy sources
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the Apache License 2.0 - see the LICENSE.txt file for details.
- Thanks to the various proxy list maintainers for providing free proxy sources
- Built with .NET 10.0
- Issues: GitHub Issues
- Discussions: GitHub Discussions
See CHANGELOG.md for a list of changes in each version.