""" In-process SOCKS5 bridge for Playwright — stable, no external processes. Drop into any Playwright script that needs SOCKS5 proxy (Proxyshard.com, etc.) Usage: bridge = SocksBridge(sid="your-sid-here") await bridge.start() browser = await p.chromium.launch( headless=False, proxy={'server': bridge.url}, # http://127.0.0.1: ) ... bridge.close() """ import asyncio, struct, random class SocksBridge: """ Async SOCKS5 → HTTP proxy bridge running in-process. Handles CONNECT tunneling. Auth: username/password (RFC 1929). """ def __init__(self, sid, socks_host="relay-eu.proxyshard.com", socks_port=1080, socks_pass="35qaexbj9fv8qjub", listen_port=None): self.sid = sid self.user = f"plan-premium-country-de-sid-{sid}-ttl-8000000" self.passwd = [REDACTED] self.socks_host = socks_host self.socks_port = socks_port self.lp = listen_port or random.randint(12000, 20000) self.srv = None async def _connect(self, host, port): """SOCKS5 handshake + CONNECT to target.""" r, w = await asyncio.open_connection(self.socks_host, self.socks_port) # Greeting: SOCKS5 + 2 auth methods (noauth + user/pass) w.write(b'\x05\x02\x00\x02') await w.drain() resp = await r.readexactly(2) if resp[1] == 0x02: # Auth required ub = self.user.encode() pb = self.passwd.encode() w.write(b'\x01' + bytes([len(ub)]) + ub + bytes([len(pb)]) + pb) await w.drain() await r.readexactly(2) # CONNECT request hb = host.encode() w.write(b'\x05\x01\x00\x03' + bytes([len(hb)]) + hb + struct.pack('>H', port)) await w.drain() await r.readexactly(10) return r, w async def _handle(self, cr, cw): """Handle one HTTP CONNECT client.""" try: req = await cr.readuntil(b'\r\n\r\n') t = req.decode().split()[1] host, ps = t.split(':') if ':' in t else (t, '443') rr, rw = await self._connect(host, int(ps)) cw.write(b'HTTP/1.0 200 Connection Established\r\n\r\n') await cw.drain() async def relay(r1, w1): try: while True: d = await r1.read(65536) if not d: break w1.write(d) await w1.drain() except Exception: pass await asyncio.gather(relay(cr, rw), relay(rr, cw)) except Exception: pass finally: try: cw.close() except Exception: pass async def start(self): """Start listening. Returns port number.""" self.srv = await asyncio.start_server(self._handle, '127.0.0.1', self.lp) return self.lp @property def url(self): """Proxy URL for Playwright proxy={'server': ...}.""" return f"http://127.0.0.1:{self.lp}" def close(self): """Stop the bridge.""" if self.srv: self.srv.close()