<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 全网低价IP</title>
    <description>The latest articles on DEV Community by 全网低价IP (@socks5ip).</description>
    <link>https://dev.to/socks5ip</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4127732%2Fa534ece7-c74c-4d1b-922e-04c4aa8b408e.jpg</url>
      <title>DEV Community: 全网低价IP</title>
      <link>https://dev.to/socks5ip</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/socks5ip"/>
    <language>en</language>
    <item>
      <title>Debugging SOCKS5 at the Wire Level: An RFC 1928 Walkthrough</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Thu, 08 Oct 2026 02:02:23 +0000</pubDate>
      <link>https://dev.to/socks5ip/debugging-socks5-at-the-wire-level-an-rfc-1928-walkthrough-3fei</link>
      <guid>https://dev.to/socks5ip/debugging-socks5-at-the-wire-level-an-rfc-1928-walkthrough-3fei</guid>
      <description>&lt;p&gt;"It works in the browser but hangs in my script." If you have run a proxy pool you have seen this line, and the usual answer is a shrug. The browser does the handshake for you and hides every step; your script inherits the failure but not the diagnosis. Reading it at the byte level collapses that ambiguity — a generic timeout becomes one specific phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four phases, strictly ordered
&lt;/h2&gt;

&lt;p&gt;SOCKS5 is small. RFC 1928 defines exactly four exchanges, and each one depends on the previous reply. A stall is almost always "the client is waiting for a reply the server will never send, because the previous message was malformed or unacceptable."&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Greeting&lt;/strong&gt; (client → proxy): &lt;code&gt;VER&lt;/code&gt;, &lt;code&gt;NMETHODS&lt;/code&gt;, then that many &lt;code&gt;METHOD&lt;/code&gt; bytes. This is the client listing the auth methods it supports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method selection&lt;/strong&gt; (proxy → client): &lt;code&gt;VER&lt;/code&gt;, &lt;code&gt;METHOD&lt;/code&gt;. The proxy picks one, or &lt;code&gt;0xFF&lt;/code&gt; for "none acceptable."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request&lt;/strong&gt; (client → proxy): &lt;code&gt;VER&lt;/code&gt;, &lt;code&gt;CMD&lt;/code&gt;, &lt;code&gt;RSV&lt;/code&gt;, &lt;code&gt;ATYP&lt;/code&gt;, &lt;code&gt;DST.ADDR&lt;/code&gt;, &lt;code&gt;DST.PORT&lt;/code&gt;. This is the actual ask — usually &lt;code&gt;CONNECT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reply&lt;/strong&gt; (proxy → client): &lt;code&gt;VER&lt;/code&gt;, &lt;code&gt;REP&lt;/code&gt;, &lt;code&gt;RSV&lt;/code&gt;, &lt;code&gt;ATYP&lt;/code&gt;, &lt;code&gt;BND.ADDR&lt;/code&gt;, &lt;code&gt;BND.PORT&lt;/code&gt;. &lt;code&gt;REP = 0x00&lt;/code&gt; means success; anything else is a structured error, not a crash.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The version byte is &lt;code&gt;0x05&lt;/code&gt; in all four. If you ever see &lt;code&gt;0x04&lt;/code&gt; in a reply, you are talking SOCKS4 to a SOCKS5 endpoint, or vice versa.&lt;/p&gt;

&lt;h2&gt;
  
  
  The byte layout, phase by phase
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Direction&lt;/th&gt;
&lt;th&gt;Fields (in order)&lt;/th&gt;
&lt;th&gt;Sizes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Greeting&lt;/td&gt;
&lt;td&gt;client → proxy&lt;/td&gt;
&lt;td&gt;VER, NMETHODS, METHODS[]&lt;/td&gt;
&lt;td&gt;1, 1, NMETHODS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method selection&lt;/td&gt;
&lt;td&gt;proxy → client&lt;/td&gt;
&lt;td&gt;VER, METHOD&lt;/td&gt;
&lt;td&gt;1, 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request&lt;/td&gt;
&lt;td&gt;client → proxy&lt;/td&gt;
&lt;td&gt;VER, CMD, RSV, ATYP, DST.ADDR, DST.PORT&lt;/td&gt;
&lt;td&gt;1, 1, 1, 1, var, 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reply&lt;/td&gt;
&lt;td&gt;proxy → client&lt;/td&gt;
&lt;td&gt;VER, REP, RSV, ATYP, BND.ADDR, BND.PORT&lt;/td&gt;
&lt;td&gt;1, 1, 1, 1, var, 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;ATYP&lt;/code&gt; decides how long &lt;code&gt;ADDR&lt;/code&gt; is: &lt;code&gt;0x01&lt;/code&gt; = 4-byte IPv4, &lt;code&gt;0x04&lt;/code&gt; = 16-byte IPv6, &lt;code&gt;0x03&lt;/code&gt; = one length byte followed by a domain name. Ports are big-endian. Getting the address type wrong is the single most common reason a hand-rolled client desynchronises: the proxy reads your domain name as raw address bytes and the stream never lines up again.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CMD&lt;/code&gt; is usually &lt;code&gt;0x01&lt;/code&gt; (&lt;code&gt;CONNECT&lt;/code&gt;). &lt;code&gt;0x02&lt;/code&gt; (&lt;code&gt;BIND&lt;/code&gt;) and &lt;code&gt;0x03&lt;/code&gt; (&lt;code&gt;UDP ASSOCIATE&lt;/code&gt;) exist, but most proxy services only implement &lt;code&gt;CONNECT&lt;/code&gt; — a &lt;code&gt;0x03&lt;/code&gt; request against such a proxy returns &lt;code&gt;REP = 0x07&lt;/code&gt; (command not supported), which is a configuration fact, not a bug in your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auth is what silently kills a connection
&lt;/h2&gt;

&lt;p&gt;Two methods carry most of the traffic: &lt;code&gt;0x00&lt;/code&gt; (no auth) and &lt;code&gt;0x02&lt;/code&gt; (username/password, defined in RFC 1929). If your client offers &lt;strong&gt;only&lt;/strong&gt; &lt;code&gt;0x02&lt;/code&gt; and the proxy is white-listed by source IP instead, it replies &lt;code&gt;METHOD = 0xFF&lt;/code&gt; and drops the connection — to your socket an empty read, not an error. That is why "authenticated" proxies work from one machine and not another: the source IP is the real credential.&lt;/p&gt;

&lt;p&gt;The practical fix is to offer both methods in the greeting and branch on the reply. Never assume the method you want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;socks5_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proxy_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy_port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;proxy_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy_port&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Greeting: offer no-auth AND user/pass
&lt;/span&gt;    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x05\x02\x00\x02&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proxy rejected all offered auth methods&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# 2. (If method == 0x02, do the RFC 1929 sub-negotiation here.)
&lt;/span&gt;    &lt;span class="c1"&gt;# 3. CONNECT with a domain name target
&lt;/span&gt;    &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x05\x01\x00\x03&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!H&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                      &lt;span class="c1"&gt;# VER REP RSV ATYP
&lt;/span&gt;    &lt;span class="n"&gt;rep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rep&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CONNECT failed, REP=0x&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rep&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# 4. Consume BND.ADDR + BND.PORT so the socket is positioned at payload
&lt;/span&gt;    &lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;0x01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x04&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;   &lt;span class="c1"&gt;# s is now a plain tunnel; write HTTP or TLS over it
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once &lt;code&gt;REP = 0x00&lt;/code&gt; and the bound address is drained, the socket behaves like a direct connection. There is no further framing — that is the whole point of SOCKS5, and the reason it tunnels protocols it knows nothing about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapping &lt;code&gt;REP&lt;/code&gt; codes to real problems
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;REP&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Usual cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;General failure&lt;/td&gt;
&lt;td&gt;Proxy backend could not open the upstream socket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x02&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Connection not allowed&lt;/td&gt;
&lt;td&gt;Egress ACL / rule rejected the target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x03&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Network unreachable&lt;/td&gt;
&lt;td&gt;Exit host has no route to the target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x04&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Host unreachable&lt;/td&gt;
&lt;td&gt;Target DNS resolved but the host is down&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x05&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Connection refused&lt;/td&gt;
&lt;td&gt;Target reachable, port closed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x06&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TTL expired&lt;/td&gt;
&lt;td&gt;Rare in practice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x07&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Command not supported&lt;/td&gt;
&lt;td&gt;You asked for &lt;code&gt;BIND&lt;/code&gt;/&lt;code&gt;UDP&lt;/code&gt; on a &lt;code&gt;CONNECT&lt;/code&gt;-only proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x08&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Address type not supported&lt;/td&gt;
&lt;td&gt;You sent IPv6 to an IPv4-only endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The distinction that saves the most time is &lt;code&gt;0x02&lt;/code&gt; versus &lt;code&gt;0x05&lt;/code&gt;. A &lt;code&gt;0x02&lt;/code&gt; means &lt;em&gt;your proxy is healthy but policy said no&lt;/em&gt; — a credential, geo, or allowlist problem. A &lt;code&gt;0x05&lt;/code&gt; means &lt;em&gt;your proxy is healthy and policy said yes, but the destination refused&lt;/em&gt; — a target-side problem. Collapsing both into "the proxy is broken" sends you debugging the wrong end of the wire.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why does &lt;code&gt;curl&lt;/code&gt; work with the same proxy but my Python socket does not?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;curl&lt;/code&gt; handles the greeting, the RFC 1929 sub-negotiation, and the reply parsing for you; your script must do all three. The usual divergence is offering the wrong auth method set, or sending &lt;code&gt;ATYP=0x01&lt;/code&gt; with a hostname.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The connection opens but every request returns an error page. Where do I look?&lt;/strong&gt;&lt;br&gt;
Past the handshake. A successful &lt;code&gt;REP = 0x00&lt;/code&gt; means the tunnel is fine, so the failure is inside the tunnelled protocol — TLS handshake, HTTP status, or the target blocking the exit's ASN. Check the exit's IP class next, not the SOCKS layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I use domain (&lt;code&gt;ATYP=0x03&lt;/code&gt;) or IP (&lt;code&gt;ATYP=0x01&lt;/code&gt;) targeting?&lt;/strong&gt;&lt;br&gt;
Prefer the domain. It lets the proxy resolve the name from &lt;em&gt;its&lt;/em&gt; network, which keeps DNS consistent with the exit IP. Sending a pre-resolved IP is a common leak: the name was resolved locally, so the DNS answer may point at the wrong region.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I check hundreds of endpoints without hand-rolling each one?&lt;/strong&gt;&lt;br&gt;
Read the bulk-validation pattern — connect, greet, and classify by &lt;code&gt;REP&lt;/code&gt; in parallel — which is covered in the &lt;a href="https://socks5ip.com.cn/ip-tools/proxy-check/batch-proxy-check/" rel="noopener noreferrer"&gt;batch proxy check guide&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;The handshake is unglamorous, but it turns "the proxy is broken" into one fixable sentence. For the client-side setup above it — Windows, mobile, browser, and router-level configuration — see the &lt;a href="https://socks5ip.com.cn/jiaochengzhongxin/socks5dailizenmeyong/" rel="noopener noreferrer"&gt;SOCKS5 usage guide&lt;/a&gt; this distils. To verify an exit before you commit to it, use the &lt;a href="https://socks5ip.com.cn/ip-check-center/" rel="noopener noreferrer"&gt;IP check center&lt;/a&gt;. Both are maintained by &lt;a href="https://socks5ip.com.cn/" rel="noopener noreferrer"&gt;socks5ip.com.cn&lt;/a&gt;; confirm current terms with each platform directly for purchase details.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Account Isolation Is More Than an IP Swap: What Actually Links Two Sessions</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Mon, 05 Oct 2026 02:08:32 +0000</pubDate>
      <link>https://dev.to/socks5ip/account-isolation-is-more-than-an-ip-swap-what-actually-links-two-sessions-4iib</link>
      <guid>https://dev.to/socks5ip/account-isolation-is-more-than-an-ip-swap-what-actually-links-two-sessions-4iib</guid>
      <description>&lt;p&gt;Two accounts, two proxies, two browser profiles — and the second is still restricted within a week. The usual conclusion is "the proxy was dirty." That is rarely the whole story. Swapping an exit changes one signal out of dozens, and the systems deciding your fate do not score signals in isolation. They score coherence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mental model: linking, not detecting
&lt;/h2&gt;

&lt;p&gt;Fraud systems rarely ask "is this a proxy?" They ask "do these sessions plausibly belong to one human, or to a coherent new one?" Every session emits signals, the system builds an entity graph, and two nodes get merged when their signals are consistent in a way random users would not be.&lt;/p&gt;

&lt;p&gt;That flips the objective. You are not trying to look &lt;em&gt;clean&lt;/em&gt;. You are trying to look &lt;em&gt;consistent&lt;/em&gt; — and consistently uninteresting.&lt;/p&gt;

&lt;p&gt;Signals cluster into four layers: &lt;strong&gt;network&lt;/strong&gt; (exit IP, ASN class, TLS/JA3, DNS resolver, WebRTC), &lt;strong&gt;environment&lt;/strong&gt; (canvas, fonts, screen metrics, timezone, locale), &lt;strong&gt;behaviour&lt;/strong&gt; (cadence, request ordering, local hours), and &lt;strong&gt;data&lt;/strong&gt; (payment, phone, recovery email). The network layer is the one a proxy can change surgically. The others follow it — or betray it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the mismatch actually shows up
&lt;/h2&gt;

&lt;p&gt;The classic failure is a &lt;em&gt;layered contradiction&lt;/em&gt;: a residential exit in Frankfurt, a browser on &lt;code&gt;Asia/Shanghai&lt;/code&gt;, &lt;code&gt;Accept-Language: zh-CN&lt;/code&gt;, a resolver in Virginia, a library-like TLS handshake. Each field is defensible alone; together they describe nobody.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;A mismatch looks like&lt;/th&gt;
&lt;th&gt;Align by&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;Exit + ASN class&lt;/td&gt;
&lt;td&gt;Residential exit, datacenter behaviour&lt;/td&gt;
&lt;td&gt;One exit class per identity, held sticky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;Timezone vs. IP geo&lt;/td&gt;
&lt;td&gt;IP in DE, clock on Asia/Shanghai&lt;/td&gt;
&lt;td&gt;Derive TZ from the exit's geolocation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Accept-Language&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;German exit, Chinese-only language list&lt;/td&gt;
&lt;td&gt;Match locale ordering to the exit region&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;DNS resolver&lt;/td&gt;
&lt;td&gt;IP in EU, resolver in US&lt;/td&gt;
&lt;td&gt;Resolve through the exit's network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;TLS / JA3&lt;/td&gt;
&lt;td&gt;Browser-like UA, library-like handshake&lt;/td&gt;
&lt;td&gt;Use a real browser stack, not a bare client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;WebRTC&lt;/td&gt;
&lt;td&gt;Real ISP leaked behind the proxy&lt;/td&gt;
&lt;td&gt;Disable it, or force it through the exit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment&lt;/td&gt;
&lt;td&gt;Fingerprint drift&lt;/td&gt;
&lt;td&gt;Canvas hash changes every session&lt;/td&gt;
&lt;td&gt;Freeze the profile; never randomise per run&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The two rules that do most of the work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One identity, one exit, held sticky.&lt;/strong&gt; Rotating per request is the fastest way to look automated: no human changes city between two page loads. Rotation belongs to stateless fetching, where there is no identity to preserve — a different problem, covered in the &lt;a href="https://socks5ip.com.cn/daili-ip-zhishiku/" rel="noopener noreferrer"&gt;proxy IP knowledge base&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coherence beats cleanliness.&lt;/strong&gt; An exit scoring a steady 20 for a month beats one scoring 0 today and 80 next Tuesday: only the first is predictable. If the IP changes character, every locale assertion built on it becomes a lie at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  A workable procedure
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pick the exit first&lt;/strong&gt; — region and class (consumer broadband for anything identity-bound), then pin it. Verify the ASN operator name, not a "residential" label.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derive the environment from the exit&lt;/strong&gt; — timezone, locale, &lt;code&gt;Accept-Language&lt;/code&gt;, and date formats come from the exit's geolocation, not your workstation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freeze the profile&lt;/strong&gt; — one per identity, no per-session randomisation. Drift &lt;em&gt;within&lt;/em&gt; an identity is as suspicious as a clone &lt;em&gt;across&lt;/em&gt; identities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close the leaks&lt;/strong&gt; — WebRTC, DNS, and any extension that can route around the proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warm up&lt;/strong&gt; — log in, browse, wait. High-risk actions on a cold session are the most common self-inflicted wound.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure before you scale&lt;/strong&gt; — run the check below on a handful of identities, not the whole fleet.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A coherence check you can run daily
&lt;/h2&gt;

&lt;p&gt;Assert that the network and environment layers agree before a session starts. Standard library only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urllib.request&lt;/span&gt;

&lt;span class="n"&gt;GEO_API&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://ipapi.co/json/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;probe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Always probe *through the exit*. A local lookup tests the wrong hop.
&lt;/span&gt;    &lt;span class="n"&gt;opener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build_opener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ProxyHandler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ProxyHandler&lt;/span&gt;&lt;span class="p"&gt;({}))&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;opener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GEO_API&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;coherence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Compare what the exit claims against what the profile asserts.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;geo &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;country_code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; != &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timezone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timezone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tz &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timezone&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; != &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timezone&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;org&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;   &lt;span class="c1"&gt;# ASN operator is the field people skip
&lt;/span&gt;        &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ASN operator missing — checker returned a stub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ACCOUNTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;        &lt;span class="c1"&gt;# {"acct-1": {"proxy": "socks5://...", "expect": {"country": "DE"}}}
&lt;/span&gt;    &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;coherence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;probe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proxy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expect&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MISMATCH: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep one expected-value record per identity; treat drift as a stop condition, not a warning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four mistakes that cost the most
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rotating per request for account work.&lt;/strong&gt; It turns a stable identity into a high-velocity pattern; nothing else compensates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mixing exit classes inside one identity.&lt;/strong&gt; Residential one hour, cloud the next, is a stronger signal than either alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trusting a single score.&lt;/strong&gt; Checkers disagree because they read different databases at different rates. Agreement between two sources is the signal; one number is a hint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forgetting the leaks.&lt;/strong&gt; DNS, WebRTC, and timezone quietly undo an otherwise correct setup. Check them every session.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Doesn't a residential IP alone solve account linking?&lt;/strong&gt;&lt;br&gt;
No. It removes one failure mode — ASN-based classification. Environment, behaviour, and data signals still do the linking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many accounts per exit is safe?&lt;/strong&gt;&lt;br&gt;
No universal number. The defensible rule is one identity per exit for anything identity-bound, and retiring an exit once an identity on it has failed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is a fingerprint browser mandatory?&lt;/strong&gt;&lt;br&gt;
For multi-account work on one machine, yes in practice: you need per-profile isolation of storage, fingerprint, and routing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I verify the setup before committing?&lt;/strong&gt;&lt;br&gt;
Complete a real login and a normal session on the target, repeat over several days, and watch variance rather than the first reading.&lt;/p&gt;




&lt;p&gt;The full guide this distils — proxy basics, scenario-to-IP-type mapping, protocol and tool choices, plus the router-level and fingerprint-browser setups — is at &lt;a href="https://socks5ip.com.cn/jiaochengzhongxin/dailiip-rumen/" rel="noopener noreferrer"&gt;代理IP与工具配置全方位指南&lt;/a&gt;. To check an exit before pinning it, use the &lt;a href="https://socks5ip.com.cn/ip-check-center/" rel="noopener noreferrer"&gt;IP check center&lt;/a&gt;. Both are maintained by &lt;a href="https://socks5ip.com.cn/" rel="noopener noreferrer"&gt;socks5ip.com.cn&lt;/a&gt;; confirm current terms with each platform directly for purchase details.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
      <category>automation</category>
    </item>
    <item>
      <title>IP Purity: What "Clean Enough" Really Means, and How to Check It</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Thu, 01 Oct 2026 02:23:42 +0000</pubDate>
      <link>https://dev.to/socks5ip/ip-purity-what-clean-enough-really-means-and-how-to-check-it-2f15</link>
      <guid>https://dev.to/socks5ip/ip-purity-what-clean-enough-really-means-and-how-to-check-it-2f15</guid>
      <description>&lt;p&gt;"Clean IP" is used as if it were a property of the address. It is not. Purity is a relationship between an address, a database, and a target — and the target's own scoring rules decide the outcome. Two checkers can disagree about the same IP in the same minute and both be correct, because they are reading different databases with different update intervals.&lt;/p&gt;

&lt;p&gt;The practical question is narrower, and it is answerable: &lt;em&gt;will this address survive the flow I am about to run?&lt;/em&gt; Three checks get you most of the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 1 — blocklists and abuse history
&lt;/h2&gt;

&lt;p&gt;The blunt instrument: is the address on a real-time blocklist, and does it carry recent abuse reports?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumer-facing consequence: sign-up flows that demand extra verification, or that silently never deliver the confirmation mail.&lt;/li&gt;
&lt;li&gt;What to look at: multiple blocklists, not one. A single clean lookup proves nothing; a single dirty one is usually decisive.&lt;/li&gt;
&lt;li&gt;Watch the &lt;em&gt;recency&lt;/em&gt;, not the flag. An address delisted six months ago behaves differently from one flagged last week.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Check 2 — ASN ownership
&lt;/h2&gt;

&lt;p&gt;This is the field that matters most, and the one people skip.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ASN type&lt;/th&gt;
&lt;th&gt;How targets read it&lt;/th&gt;
&lt;th&gt;Fits&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Consumer broadband (residential)&lt;/td&gt;
&lt;td&gt;A normal subscriber&lt;/td&gt;
&lt;td&gt;Logins, accounts, anything identity-bound&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Datacenter / cloud / hosting&lt;/td&gt;
&lt;td&gt;A server, possibly a proxy&lt;/td&gt;
&lt;td&gt;Stateless fetching, bulk collection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile carrier&lt;/td&gt;
&lt;td&gt;A real device, frequently re-assigned&lt;/td&gt;
&lt;td&gt;App-level flows, tightly rate-limited targets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⚠️ A common trap: an address can belong to a cloud provider and still be described as "residential" by a cheap checker that only reads a country field. Verify the ASN operator name, not a categorical label.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 3 — neighbourhood
&lt;/h2&gt;

&lt;p&gt;An IP's reputation is partly borrowed from the range it sits in. If the surrounding block has been heavily abused, individual addresses inherit the signal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Look for how many addresses in the same /24 are flagged.&lt;/li&gt;
&lt;li&gt;For dedicated work, prefer an exit that has been held for a while over one freshly rotated in from a noisy pool.&lt;/li&gt;
&lt;li&gt;This is also why "rotate more" is not a fix for repeated blocks: it spreads the same pattern across more addresses, and the replacements inherit the range's reputation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Two mistakes that cost the most
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Reading "connects" as "clean".&lt;/strong&gt; Connectivity is the network layer. Purity is the &lt;em&gt;reputation&lt;/em&gt; layer. A proxy can connect perfectly and still be refused at the application layer by a risk score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chasing a perfect score.&lt;/strong&gt; Public IPv4 space is recycled. The useful target is &lt;em&gt;relatively clean and stable for the duration of the task&lt;/em&gt; — not absolutely spotless. An address that scores a steady 15 for thirty days is a better asset than one that scores 0 today and 80 next Tuesday, because only the first is predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  A workable procedure
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Take 3–5 addresses from the vendor's trial allocation.&lt;/li&gt;
&lt;li&gt;Run all three checks on each, and record the numbers.&lt;/li&gt;
&lt;li&gt;Test against the &lt;em&gt;actual target&lt;/em&gt;, not against a generic checker: complete a login, submit a form, navigate a session.&lt;/li&gt;
&lt;li&gt;Repeat over several days. Look at variance, not the first reading.&lt;/li&gt;
&lt;li&gt;Commit to the tier only after the target's own behaviour has repeated.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That sequence costs nothing extra and eliminates the expensive case: paying for a month of an exit that was never going to pass the target's risk layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is there a numeric threshold for "clean"?&lt;/strong&gt;&lt;br&gt;
No industry-wide one. Some operators describe thresholds internally, but they differ by target category. Use the three checks as a profile, not a grade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does the same IP score differently on two checkers?&lt;/strong&gt;&lt;br&gt;
Different databases, different update frequencies, different weighting. Treat agreement between two or more sources as the signal; treat a single number as a hint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does a residential IP guarantee success?&lt;/strong&gt;&lt;br&gt;
No, it removes one specific failure mode (ASN-based classification). Flow shape, rate, and session behaviour still decide the outcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How often should an exit be re-checked?&lt;/strong&gt;&lt;br&gt;
Before each new workload, and periodically during long-running ones — reputations move, and the change is not announced.&lt;/p&gt;




&lt;p&gt;A combined checker covering the three fields above runs at the &lt;a href="https://socks5ip.com.cn/ip-check-center/" rel="noopener noreferrer"&gt;IP check center&lt;/a&gt;. Method notes and the underlying decision tables live in the &lt;a href="https://socks5ip.com.cn/daili-ip-zhishiku/" rel="noopener noreferrer"&gt;proxy IP knowledge base&lt;/a&gt;. Both are aggregation pages maintained by &lt;a href="https://socks5ip.com.cn/" rel="noopener noreferrer"&gt;socks5ip.com.cn&lt;/a&gt;; for anything purchase-related, confirm current terms with the platform directly.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Choosing a Proxy by Use Case: Multi-Boxing, E-commerce, Scraping, Router-Level</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Mon, 28 Sep 2026 02:40:04 +0000</pubDate>
      <link>https://dev.to/socks5ip/choosing-a-proxy-by-use-case-multi-boxing-e-commerce-scraping-router-level-314i</link>
      <guid>https://dev.to/socks5ip/choosing-a-proxy-by-use-case-multi-boxing-e-commerce-scraping-router-level-314i</guid>
      <description>&lt;p&gt;Most people buy a proxy the way they buy bandwidth: sort by price, take the cheapest tier that looks big enough, and only discover the mismatch after the first login fails. The ordering is backwards. Exit type decides whether a task is possible at all; tier and price only decide how much of it you can run. Get the order wrong and you spend the difference twice — once on the wrong tier, once on the replacement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three decisions, in order
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use case → exit type.&lt;/strong&gt; Datacenter, residential, mobile; static or rotating. This is a capability question, not a cost question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit type → the three hard numbers.&lt;/strong&gt; Swap allowance, per-exit bandwidth cap, dedicated vs shared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Those numbers → tier and price.&lt;/strong&gt; Last, not first.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Comparing price across different exit types is meaningless. A shared rotating datacenter IP and a dedicated residential IP at the same monthly cost have nothing in common operationally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use case → exit type
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;th&gt;Exit type that fits&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Game multi-boxing&lt;/td&gt;
&lt;td&gt;Dedicated SOCKS5, one exit per window&lt;/td&gt;
&lt;td&gt;Needs low latency and per-window isolation; several windows behind one exit read as a single origin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce accounts&lt;/td&gt;
&lt;td&gt;Static residential (consumer broadband ASN)&lt;/td&gt;
&lt;td&gt;Risk systems classify by ASN; datacenter ranges are the easy label&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scraping / collection&lt;/td&gt;
&lt;td&gt;Rotating residential, metered per request&lt;/td&gt;
&lt;td&gt;Needs many distinct origins; per-request billing is usually cheaper than a monthly commitment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router-level / whole-network&lt;/td&gt;
&lt;td&gt;L2TP, or SOCKS5 with router import support&lt;/td&gt;
&lt;td&gt;Applies at the device layer; confirm the panel exports a config before buying&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overseas social / streaming&lt;/td&gt;
&lt;td&gt;Foreign static residential&lt;/td&gt;
&lt;td&gt;Needs a fixed exit in the target country or city, consistent with the account's history&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The failure mode is almost never "the proxy was broken". It is "the exit type did not match the task", and no amount of tier upgrade repairs that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three hard numbers
&lt;/h2&gt;

&lt;p&gt;Once the exit type is fixed, only three properties matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Swap allowance&lt;/strong&gt; — how many times per month the exit may change, and what happens past the limit. A generous-looking tier with a 5-swap cap is unusable for anything session-bound.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bandwidth cap&lt;/strong&gt; — the ceiling on a single exit. Cheap tiers are often rate-limited rather than volume-limited; estimate from concurrency, not from the size of one request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dedicated vs shared&lt;/strong&gt; — whether another customer can hold the same IP. Shared exits inherit someone else's reputation, which is invisible until a target starts demanding verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These three are comparable across vendors in a way that "speed" is not: they are contractual, measurable, and they do not depend on the target you happen to be testing against today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where teams lose money
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Buying by unit price across tiers.&lt;/strong&gt; The cheapest tier is cheap because it is small or slow, not because the vendor is generous. Buy the tier whose ceiling sits above the workload, then compare price within that tier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating "it connects" as validation.&lt;/strong&gt; Connectivity is the entry requirement, not the test. The test is whether the target's own flow — login, form submit, in-app navigation — completes repeatedly over several days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring rotation semantics on authenticated targets.&lt;/strong&gt; If the target issues a session cookie, changing country between page two and page three is itself a signal. Collection tasks want wide rotation; account-bound tasks want one fixed exit per identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is residential always better than datacenter?&lt;/strong&gt;&lt;br&gt;
No. Datacenter exits are faster and cheaper, and for stateless collection they are often the right answer. Residential matters specifically when a risk system scores the ASN — account-bound work, logins, anything where the platform's trust in the origin affects the outcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need a dedicated IP?&lt;/strong&gt;&lt;br&gt;
Only if the workload has identity attached to it. Dedicated IPs exist to prevent other customers' behaviour from becoming your reputation. For anonymous bulk fetches, sharing is fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long should I test before committing?&lt;/strong&gt;&lt;br&gt;
Long enough to see the target's behaviour repeat. A single successful login proves the configuration; three to five days of normal activity proves the exit's reputation. Use a free trial tier to run that window before paying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if the cheapest tier is the only one in budget?&lt;/strong&gt;&lt;br&gt;
Then reduce the workload rather than the exit type. A smaller allocation of the correct exit type outperforms a large allocation of the wrong one on every metric that matters downstream.&lt;/p&gt;




&lt;p&gt;The full decision table — use case, exit type, and the three hard numbers side by side — is maintained on the &lt;a href="https://socks5ip.com.cn/daili-ip-zhishiku/" rel="noopener noreferrer"&gt;proxy IP knowledge base&lt;/a&gt;, and live per-platform tiers are listed in the &lt;a href="https://socks5ip.com.cn/jiagezhongxin/" rel="noopener noreferrer"&gt;price center&lt;/a&gt;. Both are aggregation pages; always confirm the current offer on the provider's own site before purchase.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Proxy Rotation for Scrapers: Stickiness, Rate Limits, and Backoff That Works</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Thu, 24 Sep 2026 02:03:37 +0000</pubDate>
      <link>https://dev.to/socks5ip/proxy-rotation-for-scrapers-stickiness-rate-limits-and-backoff-that-works-38o2</link>
      <guid>https://dev.to/socks5ip/proxy-rotation-for-scrapers-stickiness-rate-limits-and-backoff-that-works-38o2</guid>
      <description>&lt;p&gt;A scraper with a thousand exits still gets blocked in its first hundred requests if the traffic leaving those exits has the wrong shape. Blocks are rarely caused by one bad address. They come from the pattern around it: how fast you fire, how long you stay, and what you do when a target pushes back. Most teams treat rotation as one toggle; it is three, and rotating harder only touches the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three independent knobs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Granularity&lt;/strong&gt; — how often the exit changes: every request, every session, or pinned to a target.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate&lt;/strong&gt; — requests per second, counted per exit &lt;em&gt;and&lt;/em&gt; in aggregate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backoff&lt;/strong&gt; — what the client does when the target signals "slow down".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the rate is wrong, a larger pool is not a fix. It spreads the same abuse across more addresses and gets them flagged as a group — worse, because replacements then inherit the reputation of the range.&lt;/p&gt;

&lt;h2&gt;
  
  
  Granularity: choose by task, not by preference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Granularity&lt;/th&gt;
&lt;th&gt;Exit changes&lt;/th&gt;
&lt;th&gt;Fits&lt;/th&gt;
&lt;th&gt;Breaks when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Per request&lt;/td&gt;
&lt;td&gt;Every call&lt;/td&gt;
&lt;td&gt;Stateless pages, price feeds, parallelising one query&lt;/td&gt;
&lt;td&gt;The target binds a session to navigation; login or CSRF flows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sticky per session&lt;/td&gt;
&lt;td&gt;After N requests or T minutes&lt;/td&gt;
&lt;td&gt;Logged-in browsing, pagination, multi-step forms&lt;/td&gt;
&lt;td&gt;TTL too long → one exit carries all volume; too short → bot-like&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pinned per target&lt;/td&gt;
&lt;td&gt;Never, until retired&lt;/td&gt;
&lt;td&gt;Rate-sensitive targets, account-bound tasks&lt;/td&gt;
&lt;td&gt;The pinned exit is silently shared with another worker&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;If the target issues a session cookie, honour it.&lt;/strong&gt; A real visitor does not change country between page two and page three. What matters is not your preference but which granularity the target's session semantics allow: authentication flows need a coherent exit, anonymous page fetches do not. Account-bound tasks want one fixed address per identity; bulk collection wants a wide rotating range.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rate: the number that actually gets you blocked
&lt;/h2&gt;

&lt;p&gt;Two ceilings matter, and they are not the same:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Per-exit ceiling&lt;/strong&gt; — what a real line plausibly does. Keep concurrency per exit at 1–4 and pace requests to a few per second at most.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggregate ceiling&lt;/strong&gt; — what the site tolerates from its whole visitor population. This is what triggers a range ban, and rotation does not hide it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the pool holds N exits at b requests per second each, your crawl rate is at most &lt;code&gt;N × b&lt;/code&gt;. That expression answers "tonight or next week", so pool sizing is arithmetic, not a purchase decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backoff: read the signal before retrying
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;429 or 503 with &lt;code&gt;Retry-After&lt;/code&gt;&lt;/strong&gt; — obey the header literally. Ignoring it escalates a throttle into a ban.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;403 or 444 on one exit while others succeed&lt;/strong&gt; — retire that exit only. Tearing down the whole run because one address is spent is how an hour becomes three days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Soft blocks&lt;/strong&gt; — a 200 carrying a challenge page, an empty result set, or a truncated body. These are the expensive ones, because a naive client logs them as success and reports clean data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add jitter, and back off &lt;strong&gt;per exit rather than globally&lt;/strong&gt;, so retries do not synchronise into a burst against a single address.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pool that respects all three
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_fails&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_fails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_fails&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Token bucket: one slot per request, refilled at `rps`.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_at&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rps&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;usable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fails&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_fails&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SoftBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;200 OK whose body is a challenge page, not data.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sticky_ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;exits&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sticky_ttl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sticky_ttl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;expires&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sticky_ttl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pool exhausted: every exit is retired&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;exit_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;exit_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;opener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build_opener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ProxyHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exit_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exit_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;opener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="c1"&gt;# 200 with no payload
&lt;/span&gt;                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SoftBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%d bytes from %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;exit_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;exit_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;
        &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SoftBlock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;444&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SoftBlock&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;exit_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fails&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;               &lt;span class="c1"&gt;# retire the exit, keep the run
&lt;/span&gt;            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gave up after %d attempts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details carry the value. &lt;code&gt;pick()&lt;/code&gt; reuses a live sticky binding but still validates usability, so a retired address is never handed back. And the failure handler increments a counter instead of aborting — that is what turns a pool into a self-healing resource rather than a list you babysit.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to tell you are being blocked
&lt;/h2&gt;

&lt;p&gt;Track these per exit, not in aggregate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Success rate&lt;/strong&gt; — retire anything well below the pool median, not just at zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Median latency&lt;/strong&gt; — a sharp drop usually means a cached challenge page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Body-size distribution&lt;/strong&gt; — real pages cluster; block pages do not.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rotating every request against a session-bound target.&lt;/strong&gt; Aggressive rotation is itself a signal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating 403 as a network error.&lt;/strong&gt; Retrying the same exit against the same rejection turns a soft block permanent.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How many proxies do I need?&lt;/strong&gt;&lt;br&gt;
Set the target rate first, then divide by the per-exit budget you can defend. A pool is a rate budget, not a quantity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per request or per session?&lt;/strong&gt;&lt;br&gt;
Follow the target's session semantics. Cookies and coherent navigation mean sticky sessions with a TTL; stateless pages can rotate freely.&lt;/p&gt;




&lt;p&gt;The fuller Chinese guide behind this piece — matching pool types to scenarios, from account warm-up to bulk collection, and pairing exits with fingerprint isolation: &lt;a href="https://socks5ip.com.cn/zuixinzixun/zonghejiaocheng/zidonghuayingxiao-iphuanjing/" rel="noopener noreferrer"&gt;IP environment for automated workflows&lt;/a&gt;. To measure pool health before rotating blindly, see the &lt;a href="https://socks5ip.com.cn/ip-tools/proxy-check/batch-proxy-check/" rel="noopener noreferrer"&gt;batch proxy check&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>Residential vs Datacenter IPs: How Detection Systems Actually Tell Them Apart</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Thu, 24 Sep 2026 02:02:00 +0000</pubDate>
      <link>https://dev.to/socks5ip/residential-vs-datacenter-ips-how-detection-systems-actually-tell-them-apart-3a3c</link>
      <guid>https://dev.to/socks5ip/residential-vs-datacenter-ips-how-detection-systems-actually-tell-them-apart-3a3c</guid>
      <description>&lt;p&gt;Every request announces three things before it carries a payload: the network it came from, the organisation that registered that network, and the reverse DNS its owner published. Anti-bot systems read all three, and care little which protocol you used to reach them.&lt;/p&gt;

&lt;p&gt;So two proxies with identical credentials can have very different survival rates. The difference is rarely your configuration — it is the registry record behind the address.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "residential" actually means
&lt;/h2&gt;

&lt;p&gt;The word describes &lt;strong&gt;who an address block was allocated to&lt;/strong&gt;, not how fast it is.&lt;/p&gt;

&lt;p&gt;Registries allocate address space to organisations, and each allocation is announced under an Autonomous System with a number, a country and a registered organisation name. A block allocated to a consumer ISP — a company selling DSL, fibre or mobile subscriptions — is what the industry calls residential. A hosting company, cloud provider or colocation operator gets datacenter.&lt;/p&gt;

&lt;p&gt;The other half of the vocabulary is orthogonal: &lt;strong&gt;static vs rotating&lt;/strong&gt; is how long you keep an address, while &lt;strong&gt;residential vs datacenter&lt;/strong&gt; is what it is registered as. Two axes, four combinations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Static&lt;/th&gt;
&lt;th&gt;Rotating&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Residential&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A fixed address on a real subscriber line. Best for long-lived accounts.&lt;/td&gt;
&lt;td&gt;A pool of subscriber addresses, reassigned per request or session. Best for wide crawling.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Datacenter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A fixed address on hosting infrastructure. Cheap, fast, obvious.&lt;/td&gt;
&lt;td&gt;Hosting addresses cycled automatically. High throughput, low baseline trust.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Pricing arguments usually compare a rotating datacenter product against a static residential one, which is not a comparison at all. Read a spec as a coordinate on that grid.&lt;/p&gt;

&lt;h3&gt;
  
  
  What detectors actually look at
&lt;/h3&gt;

&lt;p&gt;No serious system decides on one field. It builds a picture and asks whether the picture is internally consistent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ASN classification.&lt;/strong&gt; The organisation behind the AS — the strongest signal and the hardest to fake.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse DNS.&lt;/strong&gt; ISPs leave recognisable PTR patterns. A block with none reads as infrastructure, not a household.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefix geometry.&lt;/strong&gt; Ranges where every host behaves identically look automated; consumer lines are sparse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reputation history.&lt;/strong&gt; A recycled residential address can be dirty; a new, exclusive datacenter address can be spotless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request coherence.&lt;/strong&gt; TLS fingerprint, header order, timezone, locale. A residential IP on a headless browser convinces nobody.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Coherence beats individual quality&lt;/strong&gt; — a modest address with a matching client outperforms a pristine one with a mismatched client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classifying an exit IP yourself
&lt;/h2&gt;

&lt;p&gt;Two free inputs — the ASN organisation name and the reverse DNS record — are enough for a first-order answer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;HOSTING_HINTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amazon&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;google&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;microsoft&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azure&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;digitalocean&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;linode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ovh&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hetzner&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vultr&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alibaba&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tencent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;RESIDENTIAL_PTR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(dsl|ppp|dial|broadband|dynamic|pool|cable|client|comcast|telecom)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;INFRA_PTR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(vps|server|cloud|host|colo|dedi|node|vm)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;asn_lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: int, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;org&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: str}. BGPView is shown; swap in any equivalent
    BGP source.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.bgpview.io/ip/%s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;classify/1.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;prefixes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prefixes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;asn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefixes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prefixes&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;asn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;org&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;asn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;asn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reverse_dns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gethostbyaddr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;herror&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gaierror&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;                     &lt;span class="c1"&gt;# a missing PTR is itself a signal
&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ip_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;is_private&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;private&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;org&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;asn_lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reverse_dns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;                     &lt;span class="c1"&gt;# positive leans residential, negative hosting
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;org&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;HOSTING_HINTS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;INFRA_PTR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;RESIDENTIAL_PTR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;residential-like&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;
             &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;datacenter-like&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ambiguous&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it across a pool rather than against one address, and print the label beside the ASN: the shape of that output says more than any single row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Judge the distribution, not the sample.&lt;/strong&gt; One ambiguous address proves nothing; a pool sold as residential that returns three quarters &lt;code&gt;datacenter-like&lt;/code&gt; is a routing problem you should have been told about. &lt;strong&gt;Cache ASN lookups by prefix&lt;/strong&gt; — every address in a /24 resolves to the same ASN.&lt;/p&gt;

&lt;p&gt;Registry data answers "what is this registered as", not "how my target treats it", so cross-check live: the &lt;a href="https://socks5ip.com.cn/ip-tools/ip-info/asnpanduanip/" rel="noopener noreferrer"&gt;IP information lookup&lt;/a&gt; returns the ASN, organisation and registration type for any address — the same field this script consumes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Assuming residential means clean.&lt;/strong&gt; Residential describes registration, not history. A recycled address inherits someone else's reputation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rotating every request when the target expects a session.&lt;/strong&gt; Aggressive rotation is a signal of its own: a real visitor's address does not change between page two and page three.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validating against the wrong target.&lt;/strong&gt; A pool can pass every connectivity check and still fail on the site you care about. Test the real destination, not an echo endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring the client side.&lt;/strong&gt; If the TLS fingerprint, timezone and language do not match the address's region, the mismatch is louder than the address is good.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Buying on price per IP alone.&lt;/strong&gt; Compare cost per &lt;em&gt;usable&lt;/em&gt; address after the replacement rate, not the sticker count.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is residential always better than datacenter?&lt;/strong&gt;&lt;br&gt;
No. Datacenter is faster and cheaper, and many targets do not care. Residential matters when a risk model penalises hosting ranges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I tell static from rotating?&lt;/strong&gt;&lt;br&gt;
Ask what happens when a session drops. Static returns the same address; rotating returns a different one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if my address returns &lt;code&gt;ambiguous&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;
Plan as if it were datacenter and test it against your real target. It usually means a small regional operator or a reseller behind another AS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I make a datacenter IP look residential?&lt;/strong&gt;&lt;br&gt;
Not convincingly. The pattern would have to hold across ASN registration, PTR records and prefix behaviour at once.&lt;/p&gt;




&lt;p&gt;The longer version of this guide, on choosing a static residential provider for cross-border selling and data collection: &lt;a href="https://socks5ip.com.cn/guowaiip/quanqiuip/haiwaiip-zhuce/2026nianhaiwaiip/" rel="noopener noreferrer"&gt;海外静态住宅IP怎么选&lt;/a&gt;. Per-platform pricing: &lt;a href="https://socks5ip.com.cn/jiagezhongxin/" rel="noopener noreferrer"&gt;pricing centre&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Validate 100+ Proxy Endpoints in Minutes Without a Paid API</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Mon, 21 Sep 2026 02:07:18 +0000</pubDate>
      <link>https://dev.to/socks5ip/how-to-validate-100-proxy-endpoints-in-minutes-without-a-paid-api-25hb</link>
      <guid>https://dev.to/socks5ip/how-to-validate-100-proxy-endpoints-in-minutes-without-a-paid-api-25hb</guid>
      <description>&lt;p&gt;A proxy pool does not fail loudly. Entries go stale one at a time: a node stops answering, an authentication credential rotates, an upstream line gets reassigned to another customer. Your pipeline keeps running, and the failures surface later as missing records, a partial dataset, or a suspension email.&lt;/p&gt;

&lt;p&gt;Checking the pool before a run is cheaper than debugging a run that went wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is actually worth testing
&lt;/h2&gt;

&lt;p&gt;Most proxy checkers return a single number — latency — and stop there. That number is the least useful of the five things you can measure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Catches&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TCP connect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dead host, closed port&lt;/td&gt;
&lt;td&gt;One socket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Real HTTP request through the proxy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auth failure, whitelist rejection, upstream outage&lt;/td&gt;
&lt;td&gt;One request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Exit IP matches expectation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Wrong node returned, pool misconfiguration&lt;/td&gt;
&lt;td&gt;Free (from the response)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slow-but-alive nodes worth deprioritising&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Header leakage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Via&lt;/code&gt;, &lt;code&gt;X-Forwarded-For&lt;/code&gt;, real IP in errors&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important one is the second. A socket that connects is not a proxy that works — plenty of dead nodes still accept TCP and then hang or reject. You have to push a real request through and read the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The checker
&lt;/h2&gt;

&lt;p&gt;This uses only the standard library. It runs the whole battery concurrently and returns a structured report.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_completed&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlparse&lt;/span&gt;

&lt;span class="c1"&gt;# Any endpoint that echoes the caller's IP works.
&lt;/span&gt;&lt;span class="n"&gt;PROBE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://ip-api.com/json/?fields=status,query,country,as&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="n"&gt;WORKERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;entry: {&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: ..., &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: ..., &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: ..., &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: ..., &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: ...}&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tcp_ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http_ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit_ip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# --- 1. TCP reachability -------------------------------------------------
&lt;/span&gt;    &lt;span class="n"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])),&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TIMEOUT&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tcp_ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tcp: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

    &lt;span class="c1"&gt;# --- 2. Real request through the proxy ----------------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# Uses a plain HTTP CONNECT-free request for SOCKS-compatible testing.
&lt;/span&gt;    &lt;span class="c1"&gt;# For a genuine SOCKS5 handshake use PySocks: socks.socksocket()
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;socks&lt;/span&gt;  &lt;span class="c1"&gt;# PySocks
&lt;/span&gt;        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;socksocket&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_proxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCKS5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;settimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TIMEOUT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;urlparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROBE_URL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;urlparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROBE_URL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; HTTP/1.1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Host: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;urlparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROBE_URL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent: pool-checker/1.0&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Connection: close&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http_ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit_ip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;as&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;healthy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WORKERS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pool_exec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;futures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool_exec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;fut&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;as_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;healthy&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http_ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;dead&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;healthy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dead&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;n1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;# ... load from your config
&lt;/span&gt;    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;healthy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;healthy &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;healthy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; / dead &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dead&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;healthy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; ms  exit=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit_ip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details that matter more than they look:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concurrency is what makes this fast.&lt;/strong&gt; 100 endpoints at 40 workers finishes in roughly the time of three bad nodes, not the sum of all of them. Serial checking with a 12-second timeout on 100 nodes can take twenty minutes when half the pool is down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The timeout has to be per-connection, not global.&lt;/strong&gt; A single global deadline means one hanging node poisons the whole batch result — which is exactly the failure mode you were trying to detect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the output
&lt;/h2&gt;

&lt;p&gt;Three patterns are worth acting on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High TCP success, low HTTP success.&lt;/strong&gt; The nodes are reachable but the upstream is failing — usually an auth problem, an IP whitelist that does not include your machine, or a subscription that expired. This is a configuration issue, not a pool-quality issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exit IPs clustered in one subnet.&lt;/strong&gt; Your pool claims geographic diversity but is routing through a handful of machines. Check the returned &lt;code&gt;as&lt;/code&gt; field: if most nodes share one ASN, the pool is not as diversified as advertised.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bimodal latency.&lt;/strong&gt; A cluster of fast nodes and a cluster of slow ones often means two different upstreams behind one entry point. Splitting them lets you route latency-sensitive work to the fast half.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Only testing on port 443.&lt;/strong&gt; Many proxy pools serve HTTP CONNECT on one port and SOCKS5 on another. Test the protocol you actually use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reusing one target site.&lt;/strong&gt; Any site with per-IP rate limits will start refusing after a few hundred checks, and you will misread that as pool failure. Use a lightweight echo endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring the check count against the probe.&lt;/strong&gt; If a source offers 45 requests per minute, 100 concurrent workers will get throttled and produce false negatives. Either throttle, or use multiple probe endpoints. The DNS-based lookup described in the &lt;a href="https://socks5ip.com.cn/ip-tools/ip-info/asnpanduanip/" rel="noopener noreferrer"&gt;ASN guide&lt;/a&gt; has no such limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating a green run as permanent.&lt;/strong&gt; Reputation and availability are both time-varying. Validate before each run, or on a schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I need PySocks?&lt;/strong&gt;&lt;br&gt;
Only for genuine SOCKS5 handshakes. For HTTP and HTTPS proxies the standard library's &lt;code&gt;urllib&lt;/code&gt; accepts a proxy URL directly, and &lt;code&gt;requests&lt;/code&gt; does the same with the &lt;code&gt;proxies&lt;/code&gt; argument.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many workers should I use?&lt;/strong&gt;&lt;br&gt;
Start at 40. Past a few hundred you will saturate the local NIC or hit probe rate limits, and the extra failures are your own doing rather than the pool's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I check without sending a request to a third party?&lt;/strong&gt;&lt;br&gt;
Not meaningfully. A handshake proves the listener exists; it does not prove the upstream works or what exit IP you get. Some target has to answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What latency should I accept?&lt;/strong&gt;&lt;br&gt;
It depends on the workload, but if the 90th percentile is above roughly ten times the median, you have a multi-tier pool and should treat the tiers separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How often should I re-validate?&lt;/strong&gt;&lt;br&gt;
Before every large run, plus a scheduled sweep on a fixed interval. Pools degrade between your runs, not during them.&lt;/p&gt;




&lt;p&gt;A longer walkthrough of the same procedure, including how the checks are scheduled and what the pass thresholds are in practice, is here: &lt;a href="https://socks5ip.com.cn/ip-tools/proxy-check/batch-proxy-check/" rel="noopener noreferrer"&gt;batch proxy validation tutorial&lt;/a&gt;. For current per-platform pricing across the providers referenced in this series, see the &lt;a href="https://socks5ip.com.cn/jiagezhongxin/" rel="noopener noreferrer"&gt;pricing centre&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>Router-Level Proxying on OpenWrt: When a SOCKS5 Client Is Not Enough</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Thu, 17 Sep 2026 08:44:34 +0000</pubDate>
      <link>https://dev.to/socks5ip/router-level-proxying-on-openwrt-when-a-socks5-client-is-not-enough-372o</link>
      <guid>https://dev.to/socks5ip/router-level-proxying-on-openwrt-when-a-socks5-client-is-not-enough-372o</guid>
      <description>&lt;p&gt;Most proxy guides assume you can install software on the device. That assumption breaks the moment the device is a smart TV, a game console, a security camera, or an IoT sensor. There is no client to configure, no SOCKS5 field to fill in.&lt;/p&gt;

&lt;p&gt;The only place left to intervene is the router.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two ways to route at the router
&lt;/h2&gt;

&lt;p&gt;Once you move the decision up to the router, you have to choose how much of the traffic to divert. That choice is between an &lt;strong&gt;application-layer redirect&lt;/strong&gt; and a &lt;strong&gt;device-level tunnel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transparent proxy (redsocks / tproxy).&lt;/strong&gt; You capture TCP traffic on the router and forward it to a SOCKS5 upstream. Rules decide which destinations get redirected. Works with any device, no per-device configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tunnel protocol (L2TP, PPTP, WireGuard, OpenVPN).&lt;/strong&gt; The router becomes a client of the upstream and pushes a default or policy route down to the LAN. Everything behind the router shares one exit.&lt;/p&gt;

&lt;p&gt;Both approaches reach the same outcome — devices with no client software get proxied. The differences show up in routing granularity, protocol support, and how much per-connection overhead you accept.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing between them
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Transparent SOCKS5&lt;/th&gt;
&lt;th&gt;L2TP tunnel&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Granularity&lt;/td&gt;
&lt;td&gt;Per-destination rules&lt;/td&gt;
&lt;td&gt;Whole tunnel, or policy routes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UDP support&lt;/td&gt;
&lt;td&gt;Requires extra work (often breaks)&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work on the same network&lt;/td&gt;
&lt;td&gt;Yes, mixed with direct traffic&lt;/td&gt;
&lt;td&gt;Yes, via policy routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical upstream product&lt;/td&gt;
&lt;td&gt;SOCKS5 proxy pool&lt;/td&gt;
&lt;td&gt;L2TP line, usually residential&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overhead&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Slightly higher (encapsulation)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Device support&lt;/td&gt;
&lt;td&gt;Anything on the LAN&lt;/td&gt;
&lt;td&gt;Anything on the LAN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best fit&lt;/td&gt;
&lt;td&gt;Selective routing, web-heavy traffic&lt;/td&gt;
&lt;td&gt;Uniform exit for all devices&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The practical rule: &lt;strong&gt;if you need different devices to exit through different IPs, use transparent SOCKS5 with rules. If every device should share one clean residential exit, use L2TP.&lt;/strong&gt; Gaming consoles, streaming boxes and cameras usually fall into the second category, because the destination application is not something you can meaningfully split by rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenWrt specifics
&lt;/h2&gt;

&lt;p&gt;OpenWrt is the common choice here because it gives you a real package manager and iptables/nftables access on cheap hardware. The shape of the setup:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For transparent SOCKS5:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LAN clients
    │
    ▼
OpenWrt (iptables/nftables rules)  ──redirect──▶  redsocks / redsocks2
    │                                                     │
    │                                                  SOCKS5 upstream
    ▼
Direct traffic (rules excluded)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You install &lt;code&gt;redsocks2&lt;/code&gt; (or &lt;code&gt;redsocks&lt;/code&gt; plus &lt;code&gt;iptables-mod-tproxy&lt;/code&gt;), point it at your upstream SOCKS5 endpoint, and add rules that mark the traffic you want redirected. A common pattern is a destination list — redirect specific domains or address ranges, leave everything else direct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# illustrative: redirect traffic marked with fwmark 0x1&lt;/span&gt;
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; OUTPUT &lt;span class="nt"&gt;-p&lt;/span&gt; tcp &lt;span class="nt"&gt;-m&lt;/span&gt; mark &lt;span class="nt"&gt;--mark&lt;/span&gt; 0x1 &lt;span class="nt"&gt;-j&lt;/span&gt; REDIRECT &lt;span class="nt"&gt;--to-ports&lt;/span&gt; 12345
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For L2TP:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WAN ──L2TP client (xl2tpd + pppd)──▶ upstream
     │
     └── LAN: default route or policy routes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenWrt's &lt;code&gt;xl2tpd&lt;/code&gt; plus &lt;code&gt;ppp-mod-pppol2tp&lt;/code&gt; handles the client side. Once the interface comes up you assign it a firewall zone and either make it the default route or use policy routing to send only chosen subnets through it. Watch the MTU — L2TP encapsulation reduces it, and a wrong MTU presents as "pages load halfway" rather than as a clean failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pitfalls that cost the most time
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;UDP does not come along for free.&lt;/strong&gt; Transparent SOCKS5 setups frequently break DNS, QUIC and game traffic because SOCKS5 UDP relay is either unsupported upstream or poorly implemented. If the devices behind the router care about UDP, prefer the tunnel approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DNS is a separate decision from routing.&lt;/strong&gt; Redirecting TCP to port 443 does nothing for DNS. If your clients still resolve names through the ISP resolver, you have a leak regardless of how good the tunnel is. Force DNS through the tunnel or to a resolver you control, and test it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The router's own traffic is easy to forget.&lt;/strong&gt; Rules placed in &lt;code&gt;OUTPUT&lt;/code&gt; cover traffic originating on the router; &lt;code&gt;PREROUTING&lt;/code&gt; covers forwarded LAN traffic. Getting this backwards produces the confusing result where the router itself is proxied but the devices behind it are not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cheap hardware has a ceiling.&lt;/strong&gt; Tunnels and transparent redirection both cost CPU. A low-end router can handle a few encrypted streams and then quietly drop throughput. Test with real load, not with a single ping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The upstream line is not the bottleneck you think it is.&lt;/strong&gt; Residential and L2TP lines are often bandwidth-capped at the product level. Negotiating 100 Mbit on the interface means nothing if the line is provisioned at 20 Mbit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying the result
&lt;/h2&gt;

&lt;p&gt;Do not trust the router UI. Verify from a client behind it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# the exit IP each device actually uses&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://api.ipify.org

&lt;span class="c"&gt;# whether DNS is resolving through the tunnel&lt;/span&gt;
dig +short whoami.akamai.net @&amp;lt;your-resolver&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run both from the router, from a laptop on the LAN, and from the device that motivated the whole exercise. A setup that works from the router and fails from the console is almost always a forwarding rule problem, not a tunnel problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I need a dedicated machine for this?&lt;/strong&gt;&lt;br&gt;
No. OpenWrt runs on hardware ranging from a 15-dollar travel router to a small x86 box. The deciding factor is throughput and whether you need containerisation, not the routing approach itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I combine both — SOCKS5 rules and an L2TP tunnel?&lt;/strong&gt;&lt;br&gt;
Yes, and it is a common production pattern: route the console and TV through L2TP for a stable residential exit, and send the traffic that needs fine-grained destination control through transparent SOCKS5.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will the ISP see what I am doing?&lt;/strong&gt;&lt;br&gt;
With L2TP the tunnel is encrypted between your router and the upstream, and the ISP sees only the tunnel endpoint. That is a transport property, not an anonymity guarantee — the upstream still sees your requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about IPv6?&lt;/strong&gt;&lt;br&gt;
Dual-stack setups are a frequent source of leaks: the tunnel carries IPv4 while IPv6 traffic goes out natively. If the upstream is IPv4-only, disable IPv6 on the LAN or route it through the tunnel explicitly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is a residential L2TP line better than a datacenter one for this?&lt;/strong&gt;&lt;br&gt;
For anything that scores traffic by network type, yes — see the ASN discussion in the &lt;a href="https://socks5ip.com.cn/ip-tools/ip-info/asnpanduanip/" rel="noopener noreferrer"&gt;IP quality guide&lt;/a&gt;. For pure bandwidth-heavy workloads where classification does not matter, a datacenter line is cheaper.&lt;/p&gt;




&lt;p&gt;The full router configuration walkthrough, including the rule sets and MTU values that worked in testing, is here: &lt;a href="https://socks5ip.com.cn/jiaochengzhongxin/openwrtjiaocheng/" rel="noopener noreferrer"&gt;OpenWrt proxy configuration tutorial&lt;/a&gt;. Current per-platform pricing for both SOCKS5 and L2TP lines is listed in the &lt;a href="https://socks5ip.com.cn/jiagezhongxin/" rel="noopener noreferrer"&gt;pricing centre&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>selfhosted</category>
      <category>networking</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What Is an ASN — and Why It Decides Whether Your Proxy Looks Legit</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Thu, 17 Sep 2026 02:01:49 +0000</pubDate>
      <link>https://dev.to/socks5ip/what-is-an-asn-and-why-it-decides-whether-your-proxy-looks-legit-47g5</link>
      <guid>https://dev.to/socks5ip/what-is-an-asn-and-why-it-decides-whether-your-proxy-looks-legit-47g5</guid>
      <description>&lt;p&gt;Every IP address belongs to an Autonomous System, and that AS carries a number. If you have ever wondered why one proxy gets blocked in minutes while another survives for weeks with identical settings, the answer is usually written in that number — not in your configuration.&lt;/p&gt;

&lt;p&gt;This post is about reading it properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an ASN actually is
&lt;/h2&gt;

&lt;p&gt;An Autonomous System is a collection of IP networks operated under a single administrative authority with a single routing policy. Every AS gets a globally unique number from the regional internet registries — an &lt;strong&gt;ASN&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A few you may recognise:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ASN&lt;/th&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;th&gt;Nature&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AS4134&lt;/td&gt;
&lt;td&gt;China Telecom&lt;/td&gt;
&lt;td&gt;Consumer broadband + some enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AS4837&lt;/td&gt;
&lt;td&gt;China Unicom&lt;/td&gt;
&lt;td&gt;Consumer broadband + some enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AS15169&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;Datacenter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AS16509&lt;/td&gt;
&lt;td&gt;Amazon&lt;/td&gt;
&lt;td&gt;Cloud / datacenter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AS14061&lt;/td&gt;
&lt;td&gt;DigitalOcean&lt;/td&gt;
&lt;td&gt;Cloud / datacenter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The distinction that matters for proxies is not &lt;em&gt;which&lt;/em&gt; company, but &lt;em&gt;what kind of network&lt;/em&gt; the AS is. Consumer broadband ASNs contain residential subscribers. Cloud and hosting ASNs contain rented virtual machines. When an anti-fraud system scores your request, this is one of the first things it looks at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why platforms treat ASN as a first-class signal
&lt;/h2&gt;

&lt;p&gt;Reputation systems have to answer one question: &lt;em&gt;does this traffic plausibly come from a real person?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A residential ISP ASN is expensive and slow to obtain at scale. Datacenter ASNs are cheap and instant. So ASN type works as a crude but effective proxy for "is this a farm."&lt;/p&gt;

&lt;p&gt;This is why the same scraper, with the same user agent and the same request rate, can succeed from a home connection and get a CAPTCHA wall from a VPS. Nothing about your code changed. Your ASN changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to look up an ASN
&lt;/h2&gt;

&lt;p&gt;Three approaches, in increasing order of convenience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. whois&lt;/strong&gt; — available on most Linux boxes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;whois &lt;span class="nt"&gt;-h&lt;/span&gt; whois.cymru.com &lt;span class="s2"&gt;" -v 8.8.8.8"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;origin&lt;/code&gt; field is the ASN, and &lt;code&gt;AS Name&lt;/code&gt; gives you the operator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. DNS, via Team Cymru&lt;/strong&gt; — no dependencies, no rate limits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig +short 8.8.8.8.origin.asn.cymru.com TXT
&lt;span class="c"&gt;# "15169 | 8.8.8.0/24 | US | arin | 1992-12-01"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. An HTTP API&lt;/strong&gt; — easiest to integrate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"http://ip-api.com/json/8.8.8.8?fields=as,asname,isp,proxy,hosting"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"as"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"AS15169 Google LLC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"asname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"GOOGLE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"isp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Google LLC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"proxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"hosting"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;hosting: true&lt;/code&gt; flag is the useful part: it is a direct answer to "is this a datacenter IP?" without you maintaining a list of ASN ranges.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four-signal check
&lt;/h2&gt;

&lt;p&gt;ASN alone is not enough. A residential IP can still be dirty — shared by thousands of users, previously abused, or listed in a spam database. Run all four:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;What it tells you&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ASN type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Residential vs datacenter vs mobile&lt;/td&gt;
&lt;td&gt;The strongest single predictor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IP type databases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How third parties classify the IP&lt;/td&gt;
&lt;td&gt;Vendors compare notes; a mismatch is a red flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocklists / risk score&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Abuse history&lt;/td&gt;
&lt;td&gt;A clean ASN does not clear an IP's past&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DNS and WebRTC leakage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Whether your real IP escapes&lt;/td&gt;
&lt;td&gt;A perfect proxy that leaks DNS is not a proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last one is the most commonly skipped. If your browser resolves DNS outside the tunnel, the destination site may never see your proxy IP at all — it sees your resolver, and often your ISP with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it in a script
&lt;/h2&gt;

&lt;p&gt;This runs the ASN portion of the check for a list of IPs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;asn_lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://ip-api.com/json/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;?fields=status,country,as,asname,isp,proxy,hosting,mobile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hosting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;datacenter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mobile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mobile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;residential&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;as&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8.8.8.8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;114.114.114.114&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;asn_lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Free tier caveat: &lt;code&gt;ip-api.com&lt;/code&gt; allows 45 requests per minute from one IP. For larger batches, throttle or split across resolvers. The DNS method above has no such limit if you only need the ASN and country.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Treating "residential ASN" as a guarantee.&lt;/strong&gt; Many residential proxy pools are sourced from devices the operator does not fully control. Quality varies enormously between vendors within the same ASN category.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring the &lt;code&gt;proxy&lt;/code&gt; flag.&lt;/strong&gt; Some databases flag known proxy ranges independently of hosting status. A residential ASN can still carry a &lt;code&gt;proxy: true&lt;/code&gt; mark if the range is widely resold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checking once.&lt;/strong&gt; IP reputation is dynamic. A pool that was clean last month may be burnt now. Validate on a schedule, not on setup day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assuming a mobile IP is always better.&lt;/strong&gt; Mobile ASNs are shared by design — hundreds of users behind one carrier NAT. For account-based work, that sharing is a liability disguised as legitimacy.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does ASN affect SEO or ad delivery?&lt;/strong&gt;&lt;br&gt;
Yes — search engines and ad networks geolocate and classify by ASN. An inconsistent ASN pattern can trigger suspicious-traffic filters independently of what your content is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I know whether an ASN is a hosting ASN?&lt;/strong&gt;&lt;br&gt;
Look for the hosting flag in an IP API, or compare against the AS's customer-facing description. Names containing Cloud, Hosting, Server, VPS, or CDN are near-certain datacenter ASNs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I move a proxy from one ASN to another?&lt;/strong&gt;&lt;br&gt;
You cannot change an IP's ASN — it is assigned at the network level. You change provider, or you change the &lt;em&gt;type&lt;/em&gt; of addressing you purchase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do two IPs from the same provider have different ASNs?&lt;/strong&gt;&lt;br&gt;
Larger providers operate multiple ASes across regions and product lines. Residential and datacenter offerings from one brand are frequently announced from different ASNs.&lt;/p&gt;




&lt;p&gt;If you want to run the four-signal check without writing the code yourself, there is a free checker here: &lt;a href="https://socks5ip.com.cn/ip-check-center/" rel="noopener noreferrer"&gt;IP quality and network-type check&lt;/a&gt;. For the platform-by-platform price comparison referenced throughout this series, see the &lt;a href="https://socks5ip.com.cn/jiagezhongxin/" rel="noopener noreferrer"&gt;proxy IP pricing centre&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>SOCKS5 vs L2TP: Choosing the Right Proxy Layer (and When You Need Both)</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Wed, 16 Sep 2026 09:47:42 +0000</pubDate>
      <link>https://dev.to/socks5ip/socks5-vs-l2tp-choosing-the-right-proxy-layer-and-when-you-need-both-2bal</link>
      <guid>https://dev.to/socks5ip/socks5-vs-l2tp-choosing-the-right-proxy-layer-and-when-you-need-both-2bal</guid>
      <description>&lt;p&gt;The question "SOCKS5 or L2TP?" is usually asked as if they were two options on the same menu. They are not. They operate at different layers of the stack, and the correct answer for a non-trivial setup is frequently "both, for different parts of the network."&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision rule
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SOCKS5 decides per application. L2TP decides per device.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That single difference explains almost every real-world choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the thing needs a proxy &lt;strong&gt;inside&lt;/strong&gt; it — a browser profile, an automation script, an emulator instance — it needs SOCKS5 (or HTTP), because that is where application-level proxy configuration exists.&lt;/li&gt;
&lt;li&gt;If the thing &lt;strong&gt;cannot run a proxy client at all&lt;/strong&gt; — a TV, a game console, a camera, an IoT device — it needs the decision made at the network layer, which means a tunnel (L2TP) or a router-level proxy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Protocol comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;OSI layer&lt;/th&gt;
&lt;th&gt;UDP&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Configured in&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SOCKS5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Session (L5)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Per application&lt;/td&gt;
&lt;td&gt;The application&lt;/td&gt;
&lt;td&gt;Browsers, automation tools, emulators, one-exit-per-profile isolation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP/HTTPS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Application (L7)&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Per application&lt;/td&gt;
&lt;td&gt;The application&lt;/td&gt;
&lt;td&gt;Simple HTTP clients, scraping where CONNECT is enough&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L2TP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data link (L2)&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Per device / network&lt;/td&gt;
&lt;td&gt;OS or router&lt;/td&gt;
&lt;td&gt;Routers, whole-home routing, devices with no proxy support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PPTP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data link (L2)&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Per device / network&lt;/td&gt;
&lt;td&gt;OS or router&lt;/td&gt;
&lt;td&gt;Legacy only — deprecated, do not build new setups on it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two rows in that table carry most of the practical weight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UDP support.&lt;/strong&gt; SOCKS5 carries UDP. L2TP does not carry it cleanly — which matters if your workload includes game traffic, QUIC, or anything else riding on UDP. If it does, the app-level route is not optional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope.&lt;/strong&gt; This is the one that forces mixed setups. A SOCKS5 proxy configured in a browser does nothing for a console plugged into the same switch. An L2TP tunnel on the router covers every device behind it — including the ones you cannot install anything on.&lt;/p&gt;

&lt;h2&gt;
  
  
  When SOCKS5 is the right call
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You need a &lt;strong&gt;different exit per browser profile&lt;/strong&gt;, and you want each profile fully isolated by construction rather than by discipline.&lt;/li&gt;
&lt;li&gt;You are running &lt;strong&gt;automation&lt;/strong&gt; (Playwright, Selenium, scripted clients) where per-request or per-session routing is the whole point.&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;UDP&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Your devices can all run the client software you are using.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tradeoff: nothing outside the configured applications is proxied. Any traffic the app sends outside that path — DNS, background calls, WebRTC — follows your normal route. This is the source of most "I set a proxy and it still leaked" incidents.&lt;/p&gt;

&lt;h2&gt;
  
  
  When L2TP is the right call
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Devices you cannot install a client on&lt;/strong&gt;: TV boxes, consoles, cameras, appliances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whole-home or whole-office routing&lt;/strong&gt; where every device should share one exit by default.&lt;/li&gt;
&lt;li&gt;You want the routing decision made &lt;strong&gt;once, at a boundary&lt;/strong&gt;, instead of configured per-application and re-verified per device.&lt;/li&gt;
&lt;li&gt;Router-level setups (OpenWrt and similar) where you control the gateway.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tradeoff: everything behind that gateway shares one exit. That is exactly the point in some scenarios and disqualifying in others — for per-account isolation, sharing an exit across all devices defeats the purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mixed setup that covers both
&lt;/h2&gt;

&lt;p&gt;The pattern that shows up most often in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌─────────────────────────────┐
                    │  Router (OpenWrt)           │
   Devices with     │  L2TP tunnel → one exit     │
   no proxy client ─┤                             │
   (TV / console)   │                             │
                    └──────────────┬──────────────┘
                                   │
   Devices with     ┌──────────────▼──────────────┐
   per-app needs ───┤  SOCKS5 per application     │
   (browsers,       │  one exit per profile       │
    automation)     └─────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;L2TP at the gateway handles the devices that cannot be configured. SOCKS5 inside each application handles the workloads that need separate exits. The two do not conflict — they apply to different traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical notes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Test the layer, not just the IP.&lt;/strong&gt; A clean IP behind a leaking DNS resolver still attributes your real origin. Verify what the destination sees, end to end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UDP is the underrated filter.&lt;/strong&gt; If you are evaluating protocols for anything interactive, check UDP support before anything else — it eliminates options quickly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PPTP is not a real choice anymore.&lt;/strong&gt; It appears in provider lists as a checkbox. Do not build a new setup on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static vs rotating applies to both.&lt;/strong&gt; L2TP tunnels can be static or rotating, and SOCKS5 lines can be either. The protocol choice and the rotation policy are independent decisions — pick the protocol by layer, then pick rotation by workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SOCKS5 = per application, UDP-capable, precise isolation. Use it where you can configure the client.&lt;/li&gt;
&lt;li&gt;L2TP = per device/network, covers anything behind the gateway. Use it where you cannot.&lt;/li&gt;
&lt;li&gt;Most real setups need both, split by whether the device can run a client.&lt;/li&gt;
&lt;li&gt;Protocol and rotation are separate decisions; decide them in that order.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full protocol reference — including where HTTP and PPTP fit and the specific selection criteria per scenario — is at &lt;a href="https://socks5ip.com.cn/daili-xieyi/" rel="noopener noreferrer"&gt;socks5ip.com.cn/daili-xieyi&lt;/a&gt;. Provider price comparison across 20+ vendors is at &lt;a href="https://socks5ip.com.cn/jiagezhongxin/" rel="noopener noreferrer"&gt;socks5ip.com.cn/jiagezhongxin&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>selfhosted</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Check If a Proxy IP Is Clean: 4 Signals That Actually Matter</title>
      <dc:creator>全网低价IP</dc:creator>
      <pubDate>Wed, 16 Sep 2026 09:47:35 +0000</pubDate>
      <link>https://dev.to/socks5ip/how-to-check-if-a-proxy-ip-is-clean-4-signals-that-actually-matter-14p4</link>
      <guid>https://dev.to/socks5ip/how-to-check-if-a-proxy-ip-is-clean-4-signals-that-actually-matter-14p4</guid>
      <description>&lt;p&gt;If you work with proxies — for scraping, for geo-testing, for anything that needs an exit IP other than your own — you have probably pasted an IP into a "proxy checker" and gotten back a confidence score between 0 and 100.&lt;/p&gt;

&lt;p&gt;Those scores are mostly useless on their own. They are one vendor's opinion, derived from signals you cannot inspect, on a scale nobody defined.&lt;/p&gt;

&lt;p&gt;The underlying signals, on the other hand, are inspectable. There are four that matter, and they are not equally weighted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short answer
&lt;/h2&gt;

&lt;p&gt;An IP is "clean" only if &lt;strong&gt;all four&lt;/strong&gt; of these hold:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ASN ownership&lt;/strong&gt; — the IP belongs to a consumer ISP, not a hosting/cloud provider&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP type classification&lt;/strong&gt; — third-party databases label it residential, not hosting or known-proxy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocklist status&lt;/strong&gt; — it does not appear in abuse/fraud databases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leak behavior&lt;/strong&gt; — DNS and WebRTC do not expose your real exit IP&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any one fails, the IP will get flagged in account-facing work regardless of how the other three look. Signal 1 is the most important, and it is the one most people skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signal 1: ASN ownership (the one that actually decides)
&lt;/h2&gt;

&lt;p&gt;Every IP belongs to an Autonomous System, and every AS has an owner. That owner is the signal anti-fraud systems weight most heavily, because it is the hardest to fake and the most stable over time.&lt;/p&gt;

&lt;p&gt;An IP announced by a consumer broadband AS looks like a home user. An IP announced by a hosting AS looks like a server — because it &lt;em&gt;is&lt;/em&gt; one. Platforms have been classifying by ASN owner for years, and it is cheap to do.&lt;/p&gt;

&lt;p&gt;Look it up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get the ASN for any IP&lt;/span&gt;
whois &lt;span class="nt"&gt;-h&lt;/span&gt; whois.cymru.com &lt;span class="s2"&gt;" -v 203.0.113.45"&lt;/span&gt;

&lt;span class="c"&gt;# Or via Team Cymru's DNS interface (no client needed)&lt;/span&gt;
dig +short 45.113.0.203.origin.asn.cymru.com TXT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get back something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;203.0.113.45 | 64512 | 203.0.113.0/24 | CN | ripencc | 2011-03-14 | AS64512 Example Broadband Co.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last field — the AS name — is what you read. "Broadband", "Telecom", "Communications" suggests consumer. "Cloud", "Hosting", "Datacenter", "VPS", "LLC" is almost always a hosting AS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A note on residential proxies specifically:&lt;/strong&gt; a residential IP is one announced by a consumer AS. A &lt;em&gt;static&lt;/em&gt; residential IP is one that stays assigned to you and does not rotate mid-session. Those are two different properties, and you need both for account-facing work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signal 2: IP type classification
&lt;/h2&gt;

&lt;p&gt;Independent databases maintain their own residential/hosting/proxy labels. They disagree with each other more often than you would expect, which is exactly why it is worth checking more than one.&lt;/p&gt;

&lt;p&gt;The useful check is whether a given database disagrees with the ASN evidence. If the AS says "consumer broadband" but two databases label the range as hosting or a known proxy pool, the range has a history you should know about.&lt;/p&gt;

&lt;p&gt;This is also where "shared" versus "dedicated" shows up. A dedicated IP has only your traffic in its history. A shared IP carries the reputation of everyone who used it before you — including, potentially, someone who burned it. That history does not appear in any single lookup; it shows up as disagreement between sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signal 3: Blocklist status
&lt;/h2&gt;

&lt;p&gt;This is the one people check first and it is the least decisive. Most blocklists are narrow, lag behind reality, and are trivially avoided by anyone actually abusing an IP.&lt;/p&gt;

&lt;p&gt;Still worth a look, because appearing on one is a hard fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Quick multi-list check (DNSBL style)&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;bl &lt;span class="k"&gt;in &lt;/span&gt;zen.spamhaus.org b.barracudacentral.org dnsbl.sorbs.net&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dig +short 45.113.0.203.&lt;span class="nv"&gt;$bl&lt;/span&gt; A&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$bl&lt;/span&gt;&lt;span class="s2"&gt;: clean"&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$bl&lt;/span&gt;&lt;span class="s2"&gt;: LISTED (&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Absence from blocklists is necessary but nowhere near sufficient. Plenty of burned IPs are absent from every public list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signal 4: DNS and WebRTC leaks
&lt;/h2&gt;

&lt;p&gt;This one is about your setup rather than the IP itself, and it is the most common way a technically clean IP still gets a connection attributed to the wrong origin.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DNS leak&lt;/strong&gt; — your queries resolve through your real ISP's resolver instead of through the proxy path. Test with a DNS leak test service while the proxy is active and confirm the resolver matches the exit region.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebRTC leak&lt;/strong&gt; — browsers can expose local and public IPs through WebRTC even when a proxy is configured at the application layer. Disable or restrict WebRTC if the application does not need it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Application-layer proxies (SOCKS5, HTTP) only cover what you route through them. Anything the application sends outside that path is not proxied — which is why a browser-level leak can attribute your real IP to a session you believed was isolated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;What to check&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;How often it fails silently&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ASN ownership&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;whois&lt;/code&gt; / Team Cymru lookup — consumer ISP vs hosting&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Highest&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rarely checked at all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type classification&lt;/td&gt;
&lt;td&gt;Two or more independent databases, and whether they agree with the ASN&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Often — sources disagree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocklist&lt;/td&gt;
&lt;td&gt;A few DNSBL lookups&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Rarely (lists lag)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leak behavior&lt;/td&gt;
&lt;td&gt;DNS leak test + WebRTC state with proxy active&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Frequently — client misconfiguration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The mistakes that cost the most time
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Trusting a single score.&lt;/strong&gt; A composite score hides which signal failed. When something breaks, you cannot tell whether to change IPs, change clients, or change the provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checking blocklists and stopping there.&lt;/strong&gt; It is the easiest check and the weakest one. An IP absent from every public list can still be announced by a hosting AS with a range that has been used for automation for years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confusing "works right now" with "clean".&lt;/strong&gt; An IP can pass every check today and be burned tomorrow, because classification is continuous and history accumulates. For account-facing work, prefer dedicated static residential over shared anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring the client.&lt;/strong&gt; Half of the real-world failures are leak or routing misconfiguration, not IP reputation. Verify what the destination actually sees, not what you configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with this
&lt;/h2&gt;

&lt;p&gt;Check signals in order: ASN first, type second, leaks third, blocklists last. If the ASN is a hosting AS and your workload is account-facing, stop there — no other signal will save it.&lt;/p&gt;

&lt;p&gt;If you want to run signals 1–4 without setting up each lookup yourself, there is a free check that reports them together at &lt;a href="https://socks5ip.com.cn/ip-check-center/" rel="noopener noreferrer"&gt;socks5ip.com.cn/ip-check-center&lt;/a&gt;. And if you are selecting providers rather than debugging one, the pooled comparison across 20+ vendors is at &lt;a href="https://socks5ip.com.cn/jiagezhongxin/" rel="noopener noreferrer"&gt;socks5ip.com.cn/jiagezhongxin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The important part is not the tool. It is knowing which signal you are actually looking at, and what a failure in that signal tells you to change.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
