Skip to content
Blog

How to detect bots using residential proxies

A practical method for investigating automation behind residential IP addresses without treating a consumer network as proof of a person or a bot.

Frederick Jahn
Frederick JahnSeptember 4, 2026
How to detect bots using residential proxies

Residential proxies make a simple IP rule much less useful. The site sees a consumer-network address, but the software choosing the requests may be somewhere else entirely.

Treat residential-network classification as a lead for investigation. Record when and how the label was produced, then compare it with client consistency, session behavior, and the action being attempted. A residential IP address is not proof of a person. It is not proof of a bot either.

The short answer

Residential-network classification can narrow the investigation, but it cannot carry the decision by itself:

  1. Establish which component observed the source address.
  2. Check whether that component is inside a trusted proxy boundary.
  3. Record the address classification and the lookup time.
  4. Compare independent client and session evidence.
  5. Apply a response for the protected route, not for an entire ISP range.

Keep an explicit unknown state when the evidence supports neither automation nor an approved client. Otherwise, missing evidence quietly becomes a human-or-bot verdict.

What a residential proxy changes

A residential proxy relays traffic through an address assigned to a consumer or small-business connection. The simplest request path looks like this:

requesting software
        |
        v
residential proxy service
        |
        v
consumer-network endpoint
        |
        v
protected application

The protected application observes the endpoint used for the final hop. That address says where the request emerged onto the internet. It does not identify the software that selected the URL, the person who owns the connection, or the party paying for the proxy service.

The FBI's residential-proxy safety alert describes several ways consumer devices can become proxy endpoints. Some owners consent to sharing bandwidth. Others may not know their device or connection is being used. This is one reason an address-level block can affect someone who did not initiate the activity you are investigating.

There is another proxy boundary closer to the application. A CDN, load balancer, or ingress proxy may be the direct peer your server sees. RFC 7239 defines the Forwarded HTTP field for cooperating proxies to pass information that would otherwise be lost, including a preceding client address.

Do not trust a forwarding field merely because it exists. Configure the first trusted ingress to remove requester-supplied Forwarded or equivalent client-IP fields before writing its own value. If trusted proxies form a chain, document which hop appends each element and parse only the trusted portion. RFC 7239 warns that the field cannot be relied on without a trustworthy chain.

Write the trust boundary down:

QuestionRecord
Where is the direct peer address observed?Named CDN, proxy, load balancer, or application socket
Which intermediaries may append forwarding data?Exact services and network ranges
Who removes untrusted incoming fields?Named component and configuration owner
Which field does the application use?Exact field and parsing rule
What happens when the chain is malformed?Reject, ignore, or mark unknown

If those answers are missing, fix the boundary before tuning a proxy rule.

Why IP reputation is incomplete

An IP intelligence result is a lookup against a dataset. It has a provider, a collection method, a timestamp, and blind spots. Keep those details beside the label.

In a 2022 study centered on China, Yang and colleagues collected residential proxy addresses that were absent from the public datasets they compared. The authors' paper is useful evidence that list coverage can be incomplete. It is not a current global benchmark. The market, collection period, and proxy services in your traffic may be different.

For each lookup, preserve the raw operational facts:

Record the provider and dataset version when available. Otherwise, record unknown rather than inferring a version.

FieldExample value
Observed addressStored in the restricted request record
ObserverEdge integration
Network owner and typeConsumer ISP, hosting, mobile, unknown
Proxy labelResidential proxy, not listed, unknown
Dataset and versionProvider plus feed or model version
Lookup timeUTC timestamp
Confidence supplied by providerRaw value, if available
Cache ageDuration since the last provider result

"Not listed" and "not a proxy" are different results. The first means the dataset has no matching label. The second is a claim that needs a documented method and an expiry time. Neither result establishes who operated the client.

Build an evidence matrix

HTTP gives the server a method, target, fields, and optional content. RFC 9110 specifies that message structure. It does not add a human identity to the request. Detection comes from comparing observations that fail in different ways.

Evidence familyQuestionUseful observationBenign counterexample
NetworkWhat path reached the trusted boundary?Address classification changes repeatedly within one taskMobile networks, VPNs, privacy relays, and corporate egress can also change the visible path
Client consistencyDo the declared client and observed environment agree?Browser headers conflict with browser capabilities or the session's earlier valuesBrowser updates, extensions, enterprise policy, and embedded webviews create unusual combinations
Session sequenceDoes the request follow the application's reachable workflow?High-cost actions repeat without the expected navigation or state transitionAPI clients, assistive technology, retries, and restored sessions may skip ordinary page order
Application outcomeWhich protected action is being repeated?One workflow consumes an explicit action budget across rotating addressesShared offices, classrooms, carrier NAT, and popular events can group unrelated users
Known identityIs there a first-party account, service credential, or verified crawler identity?The claimed client lacks its required credential or verification resultA new legitimate visitor may have no prior identity or history

Each suspicious observation has a normal counterexample. Before acting, a reviewer needs to explain why the observations belong together and why the benign explanation is less likely.

Keep raw observations separate from derived labels. For example:

{
  "network": {
    "classification": "residential-proxy",
    "datasetVersion": "record-the-version",
    "observedAt": "record-the-time"
  },
  "client": {
    "declaredFamily": "record-the-claim",
    "consistency": "unknown"
  },
  "session": {
    "workflow": "record-the-route-sequence",
    "history": "insufficient"
  },
  "decision": {
    "confidence": "unknown",
    "response": "observe"
  }
}

An analyst can tell which input changed, which dataset supplied a label, and why the decision remained unknown.

For a deeper treatment of the browser layer, read How to detect browser automation. The broader scraping policy is covered in What is web scraping?.

Run a controlled test

The test below is a protocol, not a result. Run it on a staging route with accounts, endpoints, and networks you are authorized to use. Do not enroll a third party's device or connection in a proxy test.

Experiment ID: residential-proxy-evidence-matrix-v1.

Use a four-by-two design. Cross four client types with two network paths, and keep the remaining test conditions fixed inside each comparison.

Cohort IDClient controlNetwork path
human-ordinary-networkManually operated browserOrdinary approved test connection
human-residential-networkManually operated browserAuthorized residential-proxy test path
approved-automation-ordinary-networkApproved monitoring or QA automationOrdinary approved test connection
approved-automation-residential-networkApproved monitoring or QA automationAuthorized residential-proxy test path
browser-automation-ordinary-networkTest-owned current Playwright with default settingsOrdinary approved test connection
browser-automation-residential-networkTest-owned current Playwright with default settingsAuthorized residential-proxy test path
direct-client-ordinary-networkTest-owned direct HTTP clientOrdinary approved test connection
direct-client-residential-networkTest-owned direct HTTP clientAuthorized residential-proxy test path

All clients and network paths must be authorized for the experiment. The Playwright and direct-client cohorts represent automation that the staging route's policy has not approved for access; they are not unauthorized tests.

Before the run, record the browser, automation library, direct-client version, operating system, proxy contract, IP intelligence dataset, staging build, and rule versions. Pre-register the same session count for each cohort. Twenty per cell means 160 sessions in the first run. It is a debugging exercise, not a representative population study.

Then run the protocol:

  1. Create a staging workflow with a landing page, a reachable protected route, and one bounded action such as a test search or test form submission.
  2. On the isolated staging route, record validation responses without applying their block or redirect actions to real users. If you use a Centinel monitor policy, record both the actual and returned decisions: monitor converts a block to a returned allow, but it does not change allow or redirect.
  3. Use a fresh browser profile for browser cohorts and a fresh application cookie or test credential for every session.
  4. Randomize the cohort order so a deployment or dataset refresh does not affect only one group.
  5. Attempt the same server-recognized request sequence in every session. Record which browser-only steps the direct client cannot perform.
  6. Save one row per session with its known cohort, raw evidence, derived labels, decision, and any collection failure.
  7. Review misclassifications by cohort and evidence family. Do not discard unknown or missing values.
  8. Repeat after changing one variable, such as the browser version or network provider. Do not change several variables in the same comparison.

The useful output is a table of broken assumptions. Did the network dataset label every authorized proxy session? Did it label an ordinary session? Did a browser consistency rule react to the network path even though the browser did not change? Did missing data silently become low risk?

Do not publish an accuracy rate from this staging exercise. The cohorts are small and selected, and the labels describe your test setup rather than the traffic population on a live application. Production evaluation needs reviewed outcome labels, a representative sample, and a stated cost for both false positives and false negatives.

Choose a route-specific response

The same evidence should not produce the same response everywhere. A public page, login, inventory check, and account export have different failure costs.

Route conditionEvidence statePossible responseGuardrail
Public, inexpensive readOne weak network labelAllow and observeExpire the label and retain the unknown state
Interactive routeSeveral independent inconsistenciesBounded challenge or step-up checkPrevent loops and provide an accessible fallback
Expensive actionRepeated action exceeds a documented session or account budgetRate-limit the actionReturn a defined retry path and do not rely on IP alone
Sensitive actionStrong automation evidence and missing required identityDeny under the route policyLog the rule version and provide a review path
Approved service or crawlerRequired identity verifiesApply its explicit allow policyScope access to the named routes and review the trust rule

Begin in observation mode. Compare the candidate rule with known monitoring, QA automation, accessibility flows, mobile clients, and confirmed abuse. A rule that only separates the four client types across these two test paths is not ready to protect a live route.

The scraping and AI crawler use case shows how this response ladder fits a broader resource policy.

Where Centinel fits

Centinel is a sidecar service, not the site's reverse proxy. In a supported browser flow, the collector receives browser observations and network fingerprints for the browser-to-collector connection. The customer's server-side integration sends the protected request's URL, method, IP address, referrer, headers, and session cookie to /validate.

Keep those observation points distinct when interpreting network evidence. Direct API clients do not execute the browser collector, so calling a protected endpoint does not give them a browser payload.

That boundary matters for residential-proxy work. Centinel should contribute the evidence it actually observes, preserve missing values, and leave the route response to the configured policy. It does not identify the subscriber behind an address, prove that a residential endpoint is compromised, or replace API authentication and network-layer availability controls.

See the bot management overview for the current product model. Before enabling a rule, verify which signals and responses the selected integration supports.

Sources