Skip to content

Latest commit

 

History

History
419 lines (285 loc) · 9.37 KB

File metadata and controls

419 lines (285 loc) · 9.37 KB

Quick Start

Basic Requests

Simple GET request:

import httpmorph

response = httpmorph.get('https://httpbin.org/get')
print(response.status_code)
print(response.text)

POST with JSON data:

response = httpmorph.post(
    'https://httpbin.org/post',
    json={'name': 'value'}
)
print(response.json())

POST with form data:

response = httpmorph.post(
    'https://httpbin.org/post',
    data={'field': 'value'}
)

All HTTP methods:

httpmorph.get(url)
httpmorph.post(url, data=...)
httpmorph.put(url, data=...)
httpmorph.delete(url)
httpmorph.head(url)
httpmorph.patch(url, data=...)
httpmorph.options(url)

Using Client

Create a client for more control:

client = httpmorph.Client()
response = client.get('https://example.com')

Enable HTTP/2:

client = httpmorph.Client(http2=True)
response = client.get('https://www.google.com')
print(response.http_version)  # '2.0'

Set default timeout:

client = httpmorph.Client(timeout=10)
response = client.get('https://example.com')

Using Sessions

Sessions persist cookies and headers:

session = httpmorph.Session()

# First request sets cookies
session.get('https://example.com/login')

# Subsequent requests include cookies
session.get('https://example.com/protected')

# Access cookies
print(session.cookies)

Use as context manager:

with httpmorph.Session() as session:
    response = session.get('https://example.com')

Browser Fingerprinting

Mimic Chrome browser with realistic fingerprints:

# Chrome browser profile (defaults to Chrome 143)
session = httpmorph.Session(browser='chrome')
response = session.get('https://example.com')

# Use specific Chrome version (127-143 supported)
session = httpmorph.Session(browser='chrome143')
response = session.get('https://example.com')

# Random browser selection
session = httpmorph.Session(browser='random')

The Chrome browser profile includes:

  • Chrome-specific User-Agent
  • Chrome-specific TLS cipher suites and extensions
  • Post-quantum cryptography (X25519MLKEM768)
  • Certificate compression (Brotli, with zlib fallback)
  • Chrome-specific HTTP/2 settings and priority
  • Perfect JA3N, JA4, JA4_R, and Akamai fingerprint matching
  • Chrome-like default headers (sec-ch-ua, sec-fetch-*, etc.)

OS-Specific User Agents

Simulate requests from different operating systems:

import httpmorph

# macOS (default)
session = httpmorph.Session(browser='chrome', os='macos')
# User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...

# Windows
session = httpmorph.Session(browser='chrome', os='windows')
# User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...

# Linux
session = httpmorph.Session(browser='chrome', os='linux')
# User-Agent: Mozilla/5.0 (X11; Linux x86_64) ...

Supported OS values:

  • macos - macOS / Mac OS X (default)
  • windows - Windows 10/11
  • linux - Linux distributions

The os parameter only affects the User-Agent string. All other fingerprinting characteristics (TLS, HTTP/2, JA3/JA4) remain consistent with the specified browser profile.

Request Parameters

Headers:

headers = {'User-Agent': 'MyApp/1.0'}
response = httpmorph.get(url, headers=headers)

Query parameters:

params = {'key': 'value', 'foo': 'bar'}
response = httpmorph.get(url, params=params)
# Requests: https://example.com?key=value&foo=bar

Authentication:

# Basic authentication
response = httpmorph.get(
    url,
    auth=('username', 'password')
)

Timeout:

# 5 second timeout
response = httpmorph.get(url, timeout=5)

Proxy:

# HTTP proxy
response = httpmorph.get(
    url,
    proxy='http://proxy.example.com:8080'
)

# With authentication
response = httpmorph.get(
    url,
    proxy='http://proxy.example.com:8080',
    proxy_auth=('user', 'pass')
)

# Proxy dict (requests-compatible)
proxies = {
    'http': 'http://proxy.example.com:8080',
    'https': 'https://proxy.example.com:8080'
}
response = httpmorph.get(url, proxies=proxies)

SSL verification:

# Disable SSL verification (not recommended)
response = httpmorph.get(url, verify=False)

Redirects:

# Disable redirect following
response = httpmorph.get(url, allow_redirects=False)

# Limit max redirects
response = httpmorph.get(url, max_redirects=5)

Response Object

Access response data:

response = httpmorph.get('https://httpbin.org/get')

# Status
print(response.status_code)  # 200
print(response.ok)            # True for 200-399
print(response.reason)        # 'OK'

# Content
print(response.body)          # bytes
print(response.text)          # str (decoded)
print(response.content)       # bytes (alias)

# JSON
data = response.json()

# Headers
print(response.headers)
print(response.headers['Content-Type'])

# URL
print(response.url)           # Final URL after redirects

Timing information:

print(response.total_time_us)      # Total time in microseconds
print(response.connect_time_us)    # Connection time
print(response.tls_time_us)        # TLS handshake time
print(response.first_byte_time_us) # Time to first byte
print(response.elapsed)            # As timedelta

TLS information:

print(response.tls_version)     # 'TLSv1.3'
print(response.tls_cipher)      # Cipher suite name
print(response.ja3_fingerprint) # JA3 fingerprint

HTTP version:

print(response.http_version)  # '1.1' or '2.0'

Redirect history:

print(len(response.history))  # Number of redirects
for r in response.history:
    print(r.status_code, r.url)

Error Handling

Handle exceptions:

import httpmorph

try:
    response = httpmorph.get('https://example.com', timeout=5)
    response.raise_for_status()  # Raise on 4xx/5xx
except httpmorph.Timeout:
    print('Request timed out')
except httpmorph.ConnectionError:
    print('Connection failed')
except httpmorph.HTTPError as e:
    print(f'HTTP error: {e.response.status_code}')
except httpmorph.RequestException as e:
    print(f'Request failed: {e}')

Available exceptions:

  • RequestException - Base exception
  • HTTPError - 4xx/5xx status codes (after raise_for_status)
  • ConnectionError - Connection failures
  • Timeout - Request timeout
  • TooManyRedirects - Max redirects exceeded

File Uploads

Upload files:

# Single file
files = {'file': open('report.pdf', 'rb')}
response = httpmorph.post('https://httpbin.org/post', files=files)

# Multiple files
files = {
    'file1': open('report.pdf', 'rb'),
    'file2': open('data.csv', 'rb')
}
response = httpmorph.post(url, files=files)

# With filename and content type
files = {
    'file': ('report.pdf', open('report.pdf', 'rb'), 'application/pdf')
}
response = httpmorph.post(url, files=files)

HTTP/2

Both Client and Session default to HTTP/2 to match Chrome behavior:

# Both Client and Session default to HTTP/2 (http2=True)
client = httpmorph.Client()
response = client.get('https://www.google.com')
print(response.http_version)  # '2.0'

session = httpmorph.Session(browser='chrome')
response = session.get('https://www.google.com')
print(response.http_version)  # '2.0'

# Per-request override (disable HTTP/2 for specific request)
client = httpmorph.Client()  # Defaults to HTTP/2
response = client.get('https://example.com', http2=False)

Check HTTP version:

response = client.get('https://www.google.com')
if response.http_version == '2.0':
    print('Using HTTP/2')

Async Support

Use AsyncClient for async/await:

import asyncio
import httpmorph

async def fetch():
    async with httpmorph.AsyncClient() as client:
        response = await client.get('https://httpbin.org/get')
        print(response.status_code)
        return response

asyncio.run(fetch())

Make concurrent requests:

import asyncio
import httpmorph

async def fetch_all(urls):
    async with httpmorph.AsyncClient() as client:
        tasks = [client.get(url) for url in urls]
        responses = await asyncio.gather(*tasks)
        return responses

urls = [
    'https://httpbin.org/get',
    'https://httpbin.org/headers',
    'https://httpbin.org/user-agent'
]

responses = asyncio.run(fetch_all(urls))
for response in responses:
    print(response.status_code, response.url)

Next Steps

  • See :doc:`api` for complete API reference
  • See :doc:`advanced` for advanced features
  • Check the examples directory in the repository