PhantomClient 1.0.1
See the version list below for details.
dotnet add package PhantomClient --version 1.0.1
NuGet\Install-Package PhantomClient -Version 1.0.1
<PackageReference Include="PhantomClient" Version="1.0.1" />
<PackageVersion Include="PhantomClient" Version="1.0.1" />
<PackageReference Include="PhantomClient" />
paket add PhantomClient --version 1.0.1
#r "nuget: PhantomClient, 1.0.1"
#:package PhantomClient@1.0.1
#addin nuget:?package=PhantomClient&version=1.0.1
#tool nuget:?package=PhantomClient&version=1.0.1
PhantomClient
A stealth HTTP client library for .NET that can bypass Cloudflare and most TLS handshake security measures by leveraging advanced TLS fingerprinting capabilities.
What is PhantomClient?
PhantomClient is a .NET 9.0 library that enables you to make HTTP requests that closely mimic real browsers by replicating their TLS fingerprints, making it ideal for:
- Web scraping protected sites
- API testing with anti-bot protection
- Automated testing of sites with Cloudflare or similar protection
- Bypassing TLS fingerprinting detection
Features
- ✅ Multiple browser fingerprint profiles (Chrome, Firefox, Safari, etc.)
- ✅ Support for GET and POST requests with custom headers and cookies
- ✅ Automatic cookie management and persistence
- ✅ Proxy support (HTTP, SOCKS5)
- ✅ Custom timeout configuration
- ✅ Header order preservation
- ✅ Easy-to-use async/await API
- ✅ Built on .NET 9.0 with modern C# practices
Installation
NuGet Package Manager
dotnet add package PhantomClient
Package Manager Console
Install-Package PhantomClient
Prerequisites
- .NET 9.0 SDK or later
- Node.js (v14 or later) installed on the system
Important: PhantomClient automatically installs required Node.js dependencies (node-tls-client) on first initialization. Ensure Node.js is in your system PATH.
Quick Start
using PhantomClient;
// Create a new client instance
using var client = new PhantomTLS();
// Make a simple GET request
var response = await client.GetAsync("https://example.com");
Console.WriteLine($"Status: {response.StatusCode}");
Console.WriteLine($"Body: {response.Body}");
Usage Scenarios
Scenario 1: Simple GET Request with Custom Headers
using PhantomClient;
using var client = new PhantomTLS();
var options = new RequestOptions
{
ClientIdentifier = "chrome_120",
HeadersDict = new Dictionary<string, string>
{
{ "Accept", "text/html,application/xhtml+xml" },
{ "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0" },
{ "Accept-Language", "en-US,en;q=0.9" }
}
};
var response = await client.GetAsync("https://api.example.com/data", options);
if (response.StatusCode == 200)
{
Console.WriteLine($"Success: {response.Body}");
}
Scenario 2: POST Request with JSON Data
using System.Text.Json;
using PhantomClient;
using var client = new PhantomTLS();
var payload = new { username = "testuser", password = "secret123" };
var jsonBody = JsonSerializer.Serialize(payload);
var options = new PostRequestOptions
{
ClientIdentifier = "chrome_120",
HeadersDict = new Dictionary<string, string>
{
{ "Content-Type", "application/json" },
{ "Accept", "application/json" }
},
Body = jsonBody
};
var response = await client.PostAsync("https://api.example.com/login", options);
Console.WriteLine($"Response: {response.Body}");
Scenario 3: Bypassing Cloudflare Protection
using PhantomClient;
using var client = new PhantomTLS();
var options = new RequestOptions
{
ClientIdentifier = "chrome_120", // Use latest Chrome fingerprint
HeadersDict = new Dictionary<string, string>
{
{ "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0" },
{ "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" },
{ "Accept-Language", "en-US,en;q=0.9" },
{ "Accept-Encoding", "gzip, deflate, br" },
{ "Sec-Fetch-Dest", "document" },
{ "Sec-Fetch-Mode", "navigate" },
{ "Sec-Fetch-Site", "none" }
},
TimeoutSeconds = 30
};
var response = await client.GetAsync("https://cloudflare-protected-site.com", options);
if (response.StatusCode == 200)
{
Console.WriteLine("Successfully bypassed protection!");
// Save cookies for subsequent requests
await File.WriteAllTextAsync("cookies.json",
JsonSerializer.Serialize(client.GetCookies("cloudflare-protected-site.com")));
}
Scenario 4: Session Management with Cookies
using PhantomClient;
using var client = new PhantomTLS();
// First request - Login and capture cookies
var loginOptions = new PostRequestOptions
{
ClientIdentifier = "chrome_120",
Body = "username=user&password=pass",
HeadersDict = new Dictionary<string, string>
{
{ "Content-Type", "application/x-www-form-urlencoded" }
}
};
var loginResponse = await client.PostAsync("https://example.com/login", loginOptions);
// Cookies are automatically stored in the client
// Second request - Use stored cookies
var options = new RequestOptions
{
ClientIdentifier = "chrome_120"
};
var profileResponse = await client.GetAsync("https://example.com/profile", options);
Console.WriteLine($"Profile data: {profileResponse.Body}");
// Get cookies for a specific domain
var cookies = client.GetCookies("example.com");
foreach (var cookie in cookies)
{
Console.WriteLine($"{cookie.Key}: {cookie.Value}");
}
Scenario 5: Using Proxy
using PhantomClient;
using var client = new PhantomTLS();
var options = new RequestOptions
{
ClientIdentifier = "chrome_120",
ProxyUrl = "http://proxy.example.com:8080",
TimeoutSeconds = 30
};
var response = await client.GetAsync("https://api.example.com/data", options);
Console.WriteLine($"Response via proxy: {response.Body}");
Scenario 6: Custom Browser Fingerprints
PhantomClient supports multiple browser fingerprints:
using PhantomClient;
using var client = new PhantomTLS();
// Chrome
var chromeOptions = new RequestOptions { ClientIdentifier = "chrome_120" };
// Firefox
var firefoxOptions = new RequestOptions { ClientIdentifier = "firefox_120" };
// Safari
var safariOptions = new RequestOptions { ClientIdentifier = "safari_ios_16_0" };
// Make requests with different fingerprints
var chromeResponse = await client.GetAsync("https://example.com", chromeOptions);
var firefoxResponse = await client.GetAsync("https://example.com", firefoxOptions);
Available browser identifiers include:
chrome_103,chrome_104,chrome_105,chrome_106,chrome_107,chrome_108,chrome_109,chrome_110,chrome_111,chrome_112,chrome_116_PSK,chrome_116_PSK_PQ,chrome_117,chrome_120firefox_102,firefox_104,firefox_105,firefox_106,firefox_108,firefox_110,firefox_117,firefox_120safari_15_6_1,safari_16_0,safari_ipad_15_6,safari_ios_15_5,safari_ios_15_6,safari_ios_16_0- And more...
Scenario 7: Error Handling and Retries
using PhantomClient;
using var client = new PhantomTLS();
async Task<TlsResponse?> MakeRequestWithRetry(string url, int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
try
{
var options = new RequestOptions
{
ClientIdentifier = "chrome_120",
TimeoutSeconds = 15
};
var response = await client.GetAsync(url, options);
if (response.StatusCode == 200)
return response;
Console.WriteLine($"Attempt {i + 1} failed with status: {response.StatusCode}");
}
catch (Exception ex)
{
Console.WriteLine($"Attempt {i + 1} error: {ex.Message}");
}
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i))); // Exponential backoff
}
return null;
}
var result = await MakeRequestWithRetry("https://example.com");
if (result != null)
{
Console.WriteLine("Success!");
}
API Reference
PhantomTLS Class
Methods
Task<TlsResponse> GetAsync(string url, RequestOptions? options = null)- Makes an HTTP GET request
- Parameters:
url: Target URLoptions: Optional request configuration
Task<TlsResponse> PostAsync(string url, PostRequestOptions? options = null)- Makes an HTTP POST request
- Parameters:
url: Target URLoptions: Optional request configuration with body
Dictionary<string, string> GetCookies(string domain)- Retrieves cookies for a specific domain
void ClearCookies()- Clears all stored cookies
void ClearCookies(string domain)- Clears cookies for a specific domain
RequestOptions Class
public class RequestOptions
{
public string? ClientIdentifier { get; set; } = "chrome_120";
public int TimeoutSeconds { get; set; } = 30;
public Dictionary<string, string>? HeadersDict { get; set; }
public string? ProxyUrl { get; set; }
}
PostRequestOptions Class
public class PostRequestOptions : RequestOptions
{
public string Body { get; set; } = string.Empty;
}
TlsResponse Class
public class TlsResponse
{
public int StatusCode { get; set; }
public string Body { get; set; }
public Dictionary<string, string> Headers { get; set; }
public string Target { get; set; }
}
Best Practices
- Reuse client instances: Create one
PhantomTLSinstance and reuse it for multiple requests - Dispose properly: Always use
usingstatements or callDispose()when done - Match headers to fingerprint: Use realistic headers that match your chosen browser fingerprint
- Respect rate limits: Add delays between requests to avoid detection
- Handle cookies: Use the cookie management methods for session-based workflows
Troubleshooting
"Node.js not found" error
- Ensure Node.js is installed and available in your system PATH
- Verify installation:
node --version
Timeout errors
- Increase
TimeoutSecondsin your request options - Check your network connection and proxy settings
License
MIT License - Copyright © 2025 Riadh Chebbi. All rights reserved.
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
Disclaimer
This library is intended for legitimate purposes such as testing, research, and automation of your own services. Always respect websites' Terms of Service and robots.txt files. The authors are not responsible for misuse of this library.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Jering.Javascript.NodeJS (>= 7.0.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.