PySocks
PySocks is a Python SOCKS client module that enables applications to route their network traffic through SOCKS proxy servers. It acts as a robust, modern fork of SocksiPy, offering a drop-in replacement for Python's standard `socket` module with added proxy functionalities. It is also a key underlying dependency for SOCKS proxy support in the popular `requests` library.
Warnings
- gotcha PySocks' built-in HTTP proxy support is limited to HTTP proxies that use CONNECT tunneling. For general HTTP proxying, it is highly recommended to use the native proxy support of your HTTP client library (e.g., the `proxies` argument in `requests`) instead of PySocks' direct HTTP proxy option.
- gotcha Monkey-patching the standard library's `socket` module (e.g., `socket.socket = socks.socksocket`) can be a powerful way to globally route traffic, but it is generally considered an anti-pattern in Python. It might lead to unexpected behavior with other modules or libraries that make assumptions about the standard socket.
- gotcha When configuring SOCKS proxies, especially with the `requests` library, use the `socks5h://` scheme (e.g., `socks5h://proxyhost:port`) instead of `socks5://`. The 'h' ensures that DNS resolution is performed remotely by the proxy server, preventing potential DNS leaks that could reveal your real IP address.
- gotcha Reports and discussions suggest that the PySocks project has seen limited activity and new releases in recent years, leading some to consider it 'in very bad shape' or a 'discontinued project'. While still functional and widely used (especially as a `requests` dependency), this might indicate slower bug fixes or new feature development.
Install
-
pip install pysocks -
pip install requests[socks]
Imports
- socks
import socks
- socksocket
import socks socket.socket = socks.socksocket
- set_default_proxy
import socks socks.set_default_proxy(socks.SOCKS5, 'localhost', 9050)
Quickstart
import socks
import socket
import os
from urllib.request import urlopen
# Configure proxy details from environment variables or use defaults
proxy_type = socks.SOCKS5
proxy_addr = os.environ.get('SOCKS_PROXY_HOST', '127.0.0.1')
proxy_port = int(os.environ.get('SOCKS_PROXY_PORT', 9050))
try:
# Set a default SOCKS proxy for all socket connections
socks.set_default_proxy(proxy_type, proxy_addr, proxy_port)
# Monkeypatch the standard socket module to use PySocks
socket.socket = socks.socksocket
print(f"Attempting to connect via SOCKS{proxy_type} proxy at {proxy_addr}:{proxy_port}")
# Make a request using urllib, which now uses the proxified socket
with urlopen('http://icanhazip.com') as response:
external_ip = response.read().decode('utf-8').strip()
print(f"External IP (via proxy): {external_ip}")
except socks.ProxyError as e:
print(f"Proxy connection failed: {e}. Check proxy settings and availability.")
except Exception as e:
print(f"An unexpected error occurred: {e}")