How to Detect Proxies with PHP: Code Examples & API
Learn how to detect proxies with PHP, from simple header checks to a real-time proxy detection API. Includes copy-paste PHP code examples and best practices.
How to Detect Proxies with PHP
If your site or app takes sign-ups, payments, or any user input, you will eventually need to detect proxies and VPNs in PHP to keep out fraudsters, scrapers, and bots. There are two ways to approach it: a few quick checks you can write in native PHP, and a proxy detection API that does the heavy lifting for you. This guide covers both, with copy-paste examples, and is clear about where the simple methods fall short.
Native PHP proxy checks (and where they fall short)
If you want to start without any external service, two native PHP techniques give you a basic first pass.
Check for HTTP proxy headers
The quickest native check looks for HTTP headers that proxies often add to a request. If one is present, the connection may be passing through a proxy:
$proxy_headers = array(
'HTTP_VIA', 'HTTP_X_FORWARDED_FOR', 'HTTP_FORWARDED_FOR',
'HTTP_X_FORWARDED', 'HTTP_FORWARDED', 'HTTP_CLIENT_IP',
'HTTP_FORWARDED_FOR_IP', 'HTTP_PROXY_CONNECTION',
'HTTP_X_CLUSTER_CLIENT_IP'
);
foreach ($proxy_headers as $header) {
if (!empty($_SERVER[$header])) {
// A proxy header was found. Flag for review, do not hard-block.
$proxy_suspected = true;
break;
}
}
This catches transparent proxies, but it has real limits. Anonymous and elite proxies strip these headers, so it never sees them. It also produces false positives, because mobile carriers, corporate networks, and CDNs like Cloudflare legitimately set forwarding headers. Treat a header hit as a reason to review, not to block outright.
Maintain an IP blocklist
You can also keep a list of known-bad IP addresses and reject anything that matches:
$ip_blocklist = array('203.0.113.10', '198.51.100.23');
if (!empty($_SERVER['REMOTE_ADDR']) &&
in_array($_SERVER['REMOTE_ADDR'], $ip_blocklist)) {
// Known-bad IP. Block or challenge this request.
$blocked = true;
}
This is simple and works for repeat offenders, but it does not scale. Proxy IPs rotate constantly, so a hand-maintained list goes stale almost immediately. For a managed version, an IP blocklist that updates automatically is far more practical than maintaining your own array.
A note on port scanning
Older tutorials suggest scanning the visitor's IP for open proxy ports. We no longer recommend it. Port scanning adds latency to every request, frequently misfires on legitimate users who run game servers or remote-access software, can look hostile to networks and security tools, and misses the proxies that matter most. The API approach below is both faster and far more accurate.
Why native checks are not enough
The native methods share one weakness: they only catch the easy cases. Modern fraud runs on anonymous proxies, rotating VPNs, and especially residential proxies, which route through real consumer IPs and leave none of the footprints a header check relies on. Catching those requires reputation data and behavioral signals you cannot reasonably build and maintain yourself. For the concepts behind this, see our guide on how to detect residential proxies, and note that the same blind spot applies to bot traffic hiding behind clean-looking IPs.
Detect proxies with the IPQS proxy detection API
The reliable approach is to check each IP against a service that already tracks proxies, VPNs, Tor nodes, and abusive connections in real time. The proxy and VPN detection API returns a verdict and a risk score for any IP in a single request, and it integrates in a few lines of PHP:
$api_key = 'YOUR_API_KEY';
$ip = $_SERVER['REMOTE_ADDR'];
// strictness balances accuracy vs. false positives.
// allow_public_access_points reduces false positives on
// shared mobile and corporate IPs.
$url = sprintf(
'https://www.ipqualityscore.com/api/json/ip/%s/%s' .
'?strictness=1&allow_public_access_points=true',
$api_key,
urlencode($ip)
);
$result = json_decode(file_get_contents($url), true);
if (!empty($result['success'])) {
$is_proxy = $result['proxy'] ?? false; // proxy, VPN, or Tor
$fraud_score = $result['fraud_score'] ?? 0; // 0-100 risk score
if ($is_proxy || $fraud_score >= 85) {
// Your business logic: block, challenge, or step-up verify.
}
}
A few notes on the example. The strictness parameter trades sensitivity against false positives, and allow_public_access_points reduces false positives on shared mobile and corporate IPs, which directly addresses the header-test problem above. The response includes far more than a single flag, with fields such as proxy, vpn, tor, fraud_score, recent_abuse, and bot_status. The complete list is in the response parameters documentation.
Acting on the result
How you respond should match the risk. A clean IP passes through untouched. A flagged proxy or a high fraud_score can trigger added verification, a challenge, or a block, depending on how sensitive the action is. Pairing the verdict with the numeric score lets you tune thresholds rather than relying on a single yes-or-no answer. You can also cross-reference any address with an IP reputation check, or test one directly in the free IP lookup tool, before wiring it into production.
Frequently asked questions
Can you detect proxies with PHP alone?
Partly. Native header checks and IP blocklists can catch transparent proxies and known offenders, but PHP on its own cannot reliably detect anonymous, elite, or residential proxies. Those require external reputation data, which is where a proxy detection API comes in.
How do you detect a VPN with PHP?
The same way you detect proxies. Header checks miss most VPNs, so the practical method is to query a proxy and VPN detection API, which returns a vpn flag along with a risk score for the IP address.
What is the best way to detect proxies in PHP?
Call a proxy detection API on each request and act on the proxy verdict and fraud_score, using the native checks only as a lightweight first pass. This avoids the false positives and constant maintenance that come with header tests and hand-built blocklists.
Does this work for residential proxies?
Native PHP checks do not catch residential proxies, since they use real consumer IPs with no proxy footprint. Detecting them depends on fresh reputation and behavioral data delivered through an API rather than anything you can compute locally.
Start detecting proxies in PHP
Integrating proxy detection takes only a few minutes once you have an API key. Create a free account to generate one and start scoring IPs in real time, or schedule a demo to see how IPQS detects proxies, VPNs, bots, and high-risk connections across your stack.
Share this article