Skip to main content

基于原primp 重新优化调整的请求库

Project description

Python >= 3.8 Downloads CI

🪞NEVER_PRIMP

🪞NEVER_PRIMP = Python Requests IMPersonate

The fastest python HTTP client that can impersonate web browsers.
Provides precompiled wheels:

  • 🐧 linux: amd64, aarch64, armv7 (⚠️aarch64 and armv7 builds are manylinux_2_34 compatible - ubuntu>=22.04, debian>=12);
  • 🐧 musllinux: amd64, aarch64;
  • 🪟 windows: amd64;
  • 🍏 macos: amd64, aarch64.

Table of Contents

Installation

pip install -U never_primp

Key Features

🚀 Performance Optimized

  • Connection pooling with configurable idle timeout and max connections per host
  • TCP optimization (TCP_NODELAY, TCP keepalive)
  • ~59% faster for sequential requests with connection reuse

🔒 Advanced Certificate Management

  • Uses system's native certificate store (auto-updated with OS)
  • No more certificate expiration issues
  • Custom CA bundle support

🍪 Smart Cookie Management

  • Automatic cookie persistence using wreq's native Jar API
  • Manual cookie control with get_cookies() / set_cookies()
  • Cookies survive client configuration changes

⚙️ Dynamic Configuration

  • Modify headers, proxy, and impersonation at runtime
  • No need to recreate the client
  • Thread-safe configuration updates

🔄 Retry Mechanism

  • Configurable retry count and backoff timing
  • Handle transient failures gracefully

🎭 Browser Impersonation

  • Impersonate Chrome, Safari, Edge, Firefox, OkHttp
  • Mimic TLS/JA3/JA4/HTTP2 fingerprints
  • Custom OS impersonation (Windows, macOS, Linux, Android, iOS)

Usage

I. Client

HTTP client that can impersonate web browsers.

class Client:
    """Initializes an HTTP client that can impersonate web browsers.

    Args:
        auth (tuple[str, str| None] | None): Username and password for basic authentication. Default is None.
        auth_bearer (str | None): Bearer token for authentication. Default is None.
        params (dict[str, str] | None): Default query parameters to include in all requests. Default is None.
        headers (dict[str, str] | None): Default headers to send with requests. If `impersonate` is set, this will be ignored.
        timeout (float | None): HTTP request timeout in seconds. Default is 30.
        cookie_store (bool | None): Enable a persistent cookie store. Received cookies will be preserved and included
            in additional requests. Default is True.
        referer (bool | None): Enable or disable automatic setting of the `Referer` header. Default is True.
        proxy (str | None): Proxy URL for HTTP requests. Example: "socks5://127.0.0.1:9150". Default is None.
        impersonate (str | None): Entity to impersonate. Example: "chrome_124". Default is None.
            Chrome: "chrome_100","chrome_101","chrome_104","chrome_105","chrome_106","chrome_107","chrome_108",
                "chrome_109","chrome_114","chrome_116","chrome_117","chrome_118","chrome_119","chrome_120",
                "chrome_123","chrome_124","chrome_126","chrome_127","chrome_128","chrome_129","chrome_130",
                "chrome_131","chrome_133"
            Safari: "safari_ios_16.5","safari_ios_17.2","safari_ios_17.4.1","safari_ios_18.1.1",
                "safari_15.3","safari_15.5","safari_15.6.1","safari_16","safari_16.5","safari_17.0",
                "safari_17.2.1","safari_17.4.1","safari_17.5","safari_18","safari_18.2","safari_ipad_18"
            OkHttp: "okhttp_3.9","okhttp_3.11","okhttp_3.13","okhttp_3.14","okhttp_4.9","okhttp_4.10","okhttp_5"
            Edge: "edge_101","edge_122","edge_127","edge_131"
            Firefox: "firefox_109","firefox_117","firefox_128","firefox_133","firefox_135"
            Select random: "random"
        impersonate_os (str | None): impersonate OS. Example: "windows". Default is "linux".
            Android: "android", iOS: "ios", Linux: "linux", Mac OS: "macos", Windows: "windows"
            Select random: "random"
        follow_redirects (bool | None): Whether to follow redirects. Default is True.
        max_redirects (int | None): Maximum redirects to follow. Default 20. Applies if `follow_redirects` is True.
        verify (bool | None): Verify SSL certificates. Default is True.
        ca_cert_file (str | None): Path to CA certificate store. Default is None.
        https_only (bool | None): Restrict the Client to be used with HTTPS only requests. Default is False.
        http2_only (bool | None): If true - use only HTTP/2; if false - use only HTTP/1. Default is False.
        pool_idle_timeout (float | None): Connection pool idle timeout in seconds. Default is None.
        pool_max_idle_per_host (int | None): Maximum number of idle connections per host. Default is None.
        tcp_nodelay (bool | None): Enable TCP_NODELAY (disable Nagle's algorithm). Default is None.
        tcp_keepalive (float | None): TCP keepalive interval in seconds. Default is None.
        retry_count (int | None): Maximum number of retry attempts. Default is None.
        retry_backoff (float | None): Backoff time between retries in seconds. Default is None.

    """

Client methods

The Client class provides a set of methods for making HTTP requests: get, head, options, delete, post, put, patch, each of which internally utilizes the request() method for execution. The parameters for these methods closely resemble those in httpx.

def get(
    url: str,
    params: dict[str, str] | None = None,
    headers: dict[str, str] | None = None,
    cookies: dict[str, str] | None = None,
    auth: tuple[str, str| None] | None = None,
    auth_bearer: str | None = None,
    timeout: float | None = 30,
):
    """Performs a GET request to the specified URL.

    Args:
        url (str): The URL to which the request will be made.
        params (dict[str, str] | None): A map of query parameters to append to the URL. Default is None.
        headers (dict[str, str] | None): A map of HTTP headers to send with the request. Default is None.
        cookies (dict[str, str] | None): - An optional map of cookies to send with requests as the `Cookie` header.
        auth (tuple[str, str| None] | None): A tuple containing the username and an optional password
            for basic authentication. Default is None.
        auth_bearer (str | None): A string representing the bearer token for bearer token authentication. Default is None.
        timeout (float | None): The timeout for the request in seconds. Default is 30.

    """
def post(
    url: str,
    params: dict[str, str] | None = None,
    headers: dict[str, str] | None = None,
    cookies: dict[str, str] | None = None,
    content: bytes | None = None,
    data: dict[str, Any] | None = None,
    json: Any | None = None,
    files: dict[str, str] | None = None,
    auth: tuple[str, str| None] | None = None,
    auth_bearer: str | None = None,
    timeout: float | None = 30,
):
    """Performs a POST request to the specified URL.

    Args:
        url (str): The URL to which the request will be made.
        params (dict[str, str] | None): A map of query parameters to append to the URL. Default is None.
        headers (dict[str, str] | None): A map of HTTP headers to send with the request. Default is None.
        cookies (dict[str, str] | None): - An optional map of cookies to send with requests as the `Cookie` header.
        content (bytes | None): The content to send in the request body as bytes. Default is None.
        data (dict[str, Any] | None): The form data to send in the request body. Default is None.
        json (Any | None): A JSON serializable object to send in the request body. Default is None.
        files (dict[str, str] | None): A map of file fields to file paths to be sent as multipart/form-data. Default is None.
        auth (tuple[str, str| None] | None): A tuple containing the username and an optional password
            for basic authentication. Default is None.
        auth_bearer (str | None): A string representing the bearer token for bearer token authentication. Default is None.
        timeout (float | None): The timeout for the request in seconds. Default is 30.

    """

Response object

resp.content
resp.stream()  # stream the response body in chunks of bytes
resp.cookies
resp.encoding
resp.headers
resp.json()
resp.status_code
resp.text
resp.text_markdown  # html is converted to markdown text
resp.text_plain  # html is converted to plain text
resp.text_rich  # html is converted to rich text
resp.url

Devices

Impersonate
  • Chrome: chrome_100chrome_101chrome_104chrome_105chrome_106chrome_107chrome_108chrome_109chrome_114chrome_116chrome_117chrome_118chrome_119chrome_120chrome_123chrome_124chrome_126chrome_127chrome_128chrome_129chrome_130chrome_131, chrome_133, chrome_134, chrome_135, chrome_136, chrome_137, chrome_138, chrome_139, chrome_140, chrome_141

  • Edge: edge_101edge_122edge_127, edge_131, edge_134

  • Safari: safari_ios_17.2safari_ios_17.4.1safari_ios_16.5safari_ios_18.1.1, safari_15.3safari_15.5safari_15.6.1safari_16safari_16.5safari_17.0safari_17.2.1safari_17.4.1safari_17.5safari_18safari_18.2, safari_ipad_18, safari_ipad_26, safari_ios_26, safari_26

  • OkHttp: okhttp_3.9okhttp_3.11okhttp_3.13okhttp_3.14okhttp_4.9okhttp_4.10okhttp_5

  • Firefox: firefox_109, firefox_117, firefox_128, firefox_133, firefox_135, firefox_136, firefox_139, firefox_142, firefox_143

Impersonate OS
  • android, ios, linux, macos, windows

Examples

import never_primp as primp

# Impersonate
client = primp.Client(impersonate="chrome_131", impersonate_os="windows")

# Performance optimization with connection pooling
client = primp.Client(
    impersonate="chrome_131",
    pool_idle_timeout=90.0,        # Keep connections alive for 90 seconds
    pool_max_idle_per_host=10,     # Max 10 idle connections per host
    tcp_nodelay=True,               # Disable Nagle's algorithm for lower latency
    tcp_keepalive=60.0,            # TCP keepalive every 60 seconds
)

# Retry mechanism
client = primp.Client(
    retry_count=3,                  # Retry up to 3 times
    retry_backoff=1.0,              # 1 second backoff between retries
)

# Dynamic configuration updates
client.headers = {"User-Agent": "Custom User Agent"}  # Update all headers
client.headers_update({"Referer": "https://example.com"})  # Merge new headers
client.proxy = "http://127.0.0.1:8080"  # Change proxy
client.impersonate = "chrome_133"  # Change browser impersonation
client.impersonate_os = "macos"  # Change OS impersonation

# GET request
resp = client.get("https://tls.peet.ws/api/all")

# GET request with passing params and setting timeout
params = {"param1": "value1", "param2": "value2"}
resp = client.post(url="https://httpbin.org/anything", params=params, timeout=10)

# Stream response
resp = client.get("https://nytimes")
for chunk in resp.stream():
    print(chunk)

# Cookie management - Automatic (recommended)
client = primp.Client(cookie_store=True)  # Default: enabled
resp = client.get("https://httpbin.org/cookies/set?session=abc123")
# Cookies are automatically stored and sent in subsequent requests
resp2 = client.get("https://httpbin.org/cookies")  # Session cookie automatically included

# Cookie management - Manual
cookies = {"c1_n": "c1_value", "c2_n": "c2_value"}
client.set_cookies(url="https://nytimes.com", cookies=cookies)  # Set cookies for a specific domain
resp = client.get("https://nytimes.com/", cookies=cookies)  # Or pass cookies in request

# Get cookies
all_cookies = client.get_cookies(url="https://nytimes.com")  # Get all cookies from jar
response_cookies = resp.cookies  # Get cookies from response

# POST Binary Request Data
content = b"some_data"
resp = client.post(url="https://httpbin.org/anything", content=content)

# POST Form Encoded Data
data = {"key1": "value1", "key2": "value2"}
resp = client.post(url="https://httpbin.org/anything", data=data)

# POST JSON Encoded Data
json = {"key1": "value1", "key2": "value2"}
resp = client.post(url="https://httpbin.org/anything", json=json)

# POST Multipart-Encoded Files
files = {'file1': '/home/root/file1.txt', 'file2': 'home/root/file2.txt'}
resp = client.post("https://httpbin.org/post", files=files)

# Authentication using user/password
resp = client.post(url="https://httpbin.org/anything", auth=("user", "password"))

# Authentication using auth bearer
resp = client.post(url="https://httpbin.org/anything", auth_bearer="bearerXXXXXXXXXXXXXXXXXXXX")

# Using proxy or env var PRIMP_PROXY
resp = primp.Client(proxy="http://127.0.0.1:8080")  # set proxy in Client
export PRIMP_PROXY="socks5://127.0.0.1:1080"  # set proxy as environment variable

# SSL/TLS certificate verification
# Note: Primp uses your system's native certificate store by default (auto-updated with OS)
resp = primp.Client(verify=True)  # Default: uses system certificates

# Using custom CA certificate store:
resp = primp.Client(ca_cert_file="/cert/cacert.pem")
resp = primp.Client(ca_cert_file=certifi.where())
export PRIMP_CA_BUNDLE="/home/user/Downloads/cert.pem"  # set as environment variable

# You can also use convenience functions that use a default Client instance under the hood:
# primp.get() | primp.head() | primp.options() | primp.delete() | primp.post() | primp.patch() | primp.put()
# These functions can accept the `impersonate` parameter:
resp = primp.get("https://httpbin.org/anything", impersonate="chrome_131", impersonate_os="android")

II. AsyncClient

primp.AsyncClient() is an asynchronous wrapper around the primp.Client class, offering the same functions, behavior, and input arguments.

import asyncio
import logging

import never_primp as primp

async def aget_text(url):
    async with primp.AsyncClient(impersonate="chrome_131") as client:
        resp = await client.get(url)
        return resp.text

async def main():
    urls = ["https://nytimes.com/", "https://cnn.com/", "https://abcnews.go.com/"]
    tasks = [aget_text(u) for u in urls]
    results = await asyncio.gather(*tasks)

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(main())

Disclaimer

This tool is for educational purposes only. Use it at your own risk.

Project details


Download files

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

Source Distribution

never_primp-1.0.0.tar.gz (119.9 kB view details)

Uploaded Source

Built Distributions

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

never_primp-1.0.0-cp38-abi3-win_amd64.whl (3.0 MB view details)

Uploaded CPython 3.8+Windows x86-64

never_primp-1.0.0-cp38-abi3-manylinux_2_28_x86_64.whl (3.5 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ x86-64

never_primp-1.0.0-cp38-abi3-macosx_11_0_arm64.whl (3.1 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

never_primp-1.0.0-cp38-abi3-macosx_10_12_x86_64.whl (3.2 MB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

File details

Details for the file never_primp-1.0.0.tar.gz.

File metadata

  • Download URL: never_primp-1.0.0.tar.gz
  • Upload date:
  • Size: 119.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.9.6

File hashes

Hashes for never_primp-1.0.0.tar.gz
Algorithm Hash digest
SHA256 50616b7e56bb65c352a9d59bdc579515f7c0e6f1c2a08e11e68287b724299539
MD5 5e8e847383d0aacdbfabc492eb610367
BLAKE2b-256 eabcb6ea7fb2413c4ed9d5f10ce732e87bffa0e3ebc3b81aaa9ebd20136e9aa1

See more details on using hashes here.

File details

Details for the file never_primp-1.0.0-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: never_primp-1.0.0-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.0 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for never_primp-1.0.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 64fa465e681cd7210046923014720397ec84680a2056b85a3c1a1b13c68bfc3e
MD5 a37a23e236e357037fb2ecd972670d92
BLAKE2b-256 58a84acbccb7b93a2fc7dd002eaaa07305340beb0b0bbe717d68e6ac67841efc

See more details on using hashes here.

File details

Details for the file never_primp-1.0.0-cp38-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for never_primp-1.0.0-cp38-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 885576ae9a39639d36d6ea6ecb8ca83614bcbcecf2ee3388388da18cbfea4cd9
MD5 8b9ff736e9e944f7e23bd0298d7f47d7
BLAKE2b-256 6d7aad6f27cb88a4a1b3b4e78177f7e4cddb01cdbf49d4b8b2c07888ec2af57d

See more details on using hashes here.

File details

Details for the file never_primp-1.0.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for never_primp-1.0.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8ab7aeabc60750b3ddd0ea4fbb7aa8e7099f5509afd075dd507f0d4390981cc1
MD5 c1c7dd387496223c22f53b3f49a76780
BLAKE2b-256 1ed2b2725b436e1e9c808f2b3261e43d81117861b3275c2c23f687f56a084cd9

See more details on using hashes here.

File details

Details for the file never_primp-1.0.0-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for never_primp-1.0.0-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3f8b007671f7745230e3535664d34add3957520c6866bbfeb66df761521406ec
MD5 25853173b21d9255ea91fd79bb5f4e43
BLAKE2b-256 6812a830fa2076fefbbe6745644ff576b717926a886a34923c98dbd076768fff

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 Pingdom Monitoring Sentry Error logging StatusPage Status page