Skip to main content

python-socks

CI Coverage Status PyPI version versions

The python-socks package provides a core proxy client functionality for Python. Supports SOCKS4(a), SOCKS5(h), HTTP CONNECT proxy and provides sync and async (asyncio, trio, anyio) APIs. You probably don't need to use python-socks directly. It is used internally by aiohttp-socks and httpx-socks packages.

Requirements

  • Python >= 3.9
  • async-timeout >= 5.0 (optional)
  • trio >= 0.30 (optional)
  • anyio >= 4.12 (optional)

Installation

only sync proxy support:

pip install python-socks

to include optional asyncio support:

pip install python-socks[asyncio]

to include optional trio support:

pip install python-socks[trio]

to include optional anyio support:

pip install python-socks[anyio]

Simple usage

We are making secure HTTP GET request via SOCKS5 proxy

Sync

import ssl
from python_socks.sync import Proxy


def fetch():
    proxy = Proxy.from_url("socks5://user:password@127.0.0.1:1080")

    # `connect` returns standard Python socket in blocking mode
    sock = proxy.connect(
        dest_host="check-host.net",
        dest_port=443,
    )

    sock = ssl.create_default_context().wrap_socket(
        sock=sock,
        server_hostname="check-host.net",
    )

    # fmt: off
    request = (
        b"GET /ip HTTP/1.1\r\n"
        b"Host: check-host.net\r\n"
        b"Connection: close\r\n\r\n"
    )
    # fmt: on

    sock.sendall(request)
    response = sock.recv(4096)
    print(response)


fetch()

Async (asyncio)

import asyncio
import ssl
from python_socks.async_.asyncio import Proxy


async def fetch():
    proxy = Proxy.from_url("socks5://user:password@127.0.0.1:1080")

    # `connect` returns standard Python socket in non-blocking mode
    # so we can pass it to asyncio.open_connection(...)
    sock = await proxy.connect(
        dest_host="check-host.net",
        dest_port=443,
    )

    reader, writer = await asyncio.open_connection(
        sock=sock,
        ssl=ssl.create_default_context(),
        server_hostname="check-host.net",
    )

    # fmt: off
    request = (
        b"GET /ip HTTP/1.1\r\n"
        b"Host: check-host.net\r\n"
        b"Connection: close\r\n\r\n"
    )
    # fmt: on

    writer.write(request)
    response = await reader.read(-1)
    print(response)

    writer.close()
    await writer.wait_closed()


asyncio.run(fetch())

Async (trio)

import ssl
import trio
from python_socks.async_.trio import Proxy


async def fetch():
    proxy = Proxy.from_url("socks5://user:password@127.0.0.1:1080")

    # `connect` returns trio.socket.SocketType
    # so we can pass it to trio.SocketStream
    sock = await proxy.connect(
        dest_host="check-host.net",
        dest_port=443,
    )
    stream = trio.SocketStream(sock)
    stream = trio.SSLStream(
        stream,
        ssl_context=ssl.create_default_context(),
        server_hostname="check-host.net",
    )
    await stream.do_handshake()

    # fmt: off
    request = (
        b"GET /ip HTTP/1.1\r\n"
        b"Host: check-host.net\r\n"
        b"Connection: close\r\n\r\n"
    )
    # fmt: on

    await stream.send_all(request)
    response = await stream.receive_some(4096)
    print(response)

    await stream.aclose()


trio.run(fetch)

Async (anyio)

import ssl
import anyio
from anyio.streams.tls import TLSStream
from python_socks.async_.anyio import Proxy


async def fetch():
    proxy = Proxy.from_url("socks5://user:password@127.0.0.1:1080")

    # `connect` returns anyio.abc.SocketStream
    # we can use it directly
    stream = await proxy.connect(
        dest_host="check-host.net",
        dest_port=443,
    )
    stream = await TLSStream.wrap(
        stream,
        ssl_context=ssl.create_default_context(),
        hostname="check-host.net",
    )

    # fmt: off
    request = (
        b"GET /ip HTTP/1.1\r\n"
        b"Host: check-host.net\r\n"
        b"Connection: close\r\n\r\n"
    )
    # fmt: on

    await stream.send(request)
    response = await stream.receive(4096)
    print(response)

    await stream.aclose()


anyio.run(fetch)

More complex example

A urllib3 PoolManager that routes connections via the proxy

from urllib3 import PoolManager, HTTPConnectionPool, HTTPSConnectionPool
from urllib3.connection import HTTPConnection, HTTPSConnection
from python_socks.sync import Proxy


class ProxyHTTPConnection(HTTPConnection):
    def __init__(self, *args, **kwargs):
        socks_options = kwargs.pop("_socks_options")
        self._proxy_url = socks_options["proxy_url"]
        super().__init__(*args, **kwargs)

    def _new_conn(self):
        proxy = Proxy.from_url(self._proxy_url)
        return proxy.connect(
            dest_host=self.host,
            dest_port=self.port,
            timeout=self.timeout,
        )


class ProxyHTTPSConnection(ProxyHTTPConnection, HTTPSConnection):
    pass


class ProxyHTTPConnectionPool(HTTPConnectionPool):
    ConnectionCls = ProxyHTTPConnection


class ProxyHTTPSConnectionPool(HTTPSConnectionPool):
    ConnectionCls = ProxyHTTPSConnection


class ProxyPoolManager(PoolManager):
    def __init__(
        self,
        proxy_url,
        timeout=5,
        num_pools=10,
        headers=None,
        **connection_pool_kw,
    ):

        connection_pool_kw["_socks_options"] = {"proxy_url": proxy_url}
        connection_pool_kw["timeout"] = timeout

        super().__init__(num_pools, headers, **connection_pool_kw)

        self.pool_classes_by_scheme = {
            "http": ProxyHTTPConnectionPool,
            "https": ProxyHTTPSConnectionPool,
        }


### and how to use it
manager = ProxyPoolManager("socks5://user:password@127.0.0.1:1080")
response = manager.request("GET", "https://check-host.net/ip")
print(response.data)

Proxy Chaining (sync example — same for asyncio, trio, anyio)

import ssl
from python_socks.sync import Proxy


def fetch():
    proxy1 = Proxy.from_url("socks5://user:password@127.0.0.1:1080")
    proxy2 = Proxy.from_url("socks4://127.0.0.1:1081", forward=proxy1)
    proxy3 = Proxy.from_url("http://user:password@127.0.0.1:1082", forward=proxy2)

    sock = proxy3.connect(
        dest_host="check-host.net",
        dest_port=443,
    )

    sock = ssl.create_default_context().wrap_socket(
        sock=sock,
        server_hostname="check-host.net",
    )

    # fmt: off
    request = (
        b"GET /ip HTTP/1.1\r\n"
        b"Host: check-host.net\r\n"
        b"Connection: close\r\n\r\n"
    )
    # fmt: on

    sock.sendall(request)
    response = sock.recv(4096)
    print(response)


fetch()

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_socks-3.0.0.tar.gz (232.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_socks-3.0.0-py3-none-any.whl (49.5 kB view details)

Uploaded Python 3

File details

Details for the file python_socks-3.0.0.tar.gz.

File metadata

  • Download URL: python_socks-3.0.0.tar.gz
  • Upload date:
  • Size: 232.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for python_socks-3.0.0.tar.gz
Algorithm Hash digest
SHA256 c20ddf978b5c90467bf242757a11dcd00d7c8bd339901de1839b492d5571ab7f
MD5 ef0786fd2fdfb93f01eade0b385dc8c3
BLAKE2b-256 6c6bbd9e15e67cf42b318970028a572750924adbe28776e8420fcdfe60838c61

See more details on using hashes here.

File details

Details for the file python_socks-3.0.0-py3-none-any.whl.

File metadata

  • Download URL: python_socks-3.0.0-py3-none-any.whl
  • Upload date:
  • Size: 49.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for python_socks-3.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e06a421d4d7f3fc17ef2740ab6c291640364f6a362b94a1ae87a136c29bd0067
MD5 52b02a54959e5861582051826ad9af7a
BLAKE2b-256 ebe7af080d0d2d5bbc3dbdf58a805812ee45175c5c32c6673f23a5480f9785c2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page