The next generation HTTP client.
npx @tessl/cli install tessl/pypi-httpx@0.28.00
# httpx
1
2
A fully featured HTTP client library for Python 3 with both synchronous and asynchronous APIs, HTTP/2 support, and modern capabilities.
3
4
## Package Information
5
6
- **Package Name**: httpx
7
- **Language**: Python
8
- **Installation**: `pip install httpx`
9
10
## Core Imports
11
12
```python
13
import httpx
14
15
# For direct access to key classes
16
from httpx import Client, AsyncClient, Response, Request
17
18
# For authentication
19
from httpx import BasicAuth, DigestAuth
20
21
# For configuration
22
from httpx import Timeout, Limits, Proxy
23
24
# For data structures
25
from httpx import Headers, Cookies, URL, QueryParams
26
27
# For exceptions
28
from httpx import HTTPError, HTTPStatusError, RequestError
29
30
# Constants
31
from httpx import USE_CLIENT_DEFAULT
32
```
33
34
## Basic Usage
35
36
```python
37
import httpx
38
39
# Simple GET request
40
response = httpx.get('https://httpbin.org/get')
41
print(response.status_code)
42
print(response.json())
43
44
# POST with data
45
response = httpx.post('https://httpbin.org/post', json={'key': 'value'})
46
47
# Using a client for multiple requests
48
with httpx.Client() as client:
49
response = client.get('https://httpbin.org/get')
50
print(response.text)
51
```
52
53
## Architecture
54
55
httpx provides two main approaches for making HTTP requests:
56
57
1. **Top-level functions** - Convenient for single requests (`httpx.get()`, `httpx.post()`, etc.)
58
2. **Client classes** - Efficient for multiple requests with connection pooling (`httpx.Client`, `httpx.AsyncClient`)
59
60
The library supports both synchronous and asynchronous programming patterns with equivalent APIs.
61
62
## Capabilities
63
64
### Request Functions
65
66
Top-level convenience functions for making HTTP requests without managing a client instance.
67
68
```python { .api }
69
def get(
70
url: URL | str,
71
*,
72
params: QueryParamTypes | None = None,
73
headers: HeaderTypes | None = None,
74
cookies: CookieTypes | None = None,
75
auth: AuthTypes | None = None,
76
proxy: ProxyTypes | None = None,
77
follow_redirects: bool = False,
78
verify: ssl.SSLContext | str | bool = True,
79
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
80
trust_env: bool = True,
81
) -> Response:
82
"""Send a GET request."""
83
84
def post(
85
url: URL | str,
86
*,
87
content: RequestContent | None = None,
88
data: RequestData | None = None,
89
files: RequestFiles | None = None,
90
json: Any | None = None,
91
params: QueryParamTypes | None = None,
92
headers: HeaderTypes | None = None,
93
cookies: CookieTypes | None = None,
94
auth: AuthTypes | None = None,
95
proxy: ProxyTypes | None = None,
96
follow_redirects: bool = False,
97
verify: ssl.SSLContext | str | bool = True,
98
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
99
trust_env: bool = True,
100
) -> Response:
101
"""Send a POST request."""
102
103
def put(
104
url: URL | str,
105
*,
106
content: RequestContent | None = None,
107
data: RequestData | None = None,
108
files: RequestFiles | None = None,
109
json: Any | None = None,
110
params: QueryParamTypes | None = None,
111
headers: HeaderTypes | None = None,
112
cookies: CookieTypes | None = None,
113
auth: AuthTypes | None = None,
114
proxy: ProxyTypes | None = None,
115
follow_redirects: bool = False,
116
verify: ssl.SSLContext | str | bool = True,
117
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
118
trust_env: bool = True,
119
) -> Response:
120
"""Send a PUT request."""
121
122
def patch(
123
url: URL | str,
124
*,
125
content: RequestContent | None = None,
126
data: RequestData | None = None,
127
files: RequestFiles | None = None,
128
json: Any | None = None,
129
params: QueryParamTypes | None = None,
130
headers: HeaderTypes | None = None,
131
cookies: CookieTypes | None = None,
132
auth: AuthTypes | None = None,
133
proxy: ProxyTypes | None = None,
134
follow_redirects: bool = False,
135
verify: ssl.SSLContext | str | bool = True,
136
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
137
trust_env: bool = True,
138
) -> Response:
139
"""Send a PATCH request."""
140
141
def delete(
142
url: URL | str,
143
*,
144
params: QueryParamTypes | None = None,
145
headers: HeaderTypes | None = None,
146
cookies: CookieTypes | None = None,
147
auth: AuthTypes | None = None,
148
proxy: ProxyTypes | None = None,
149
follow_redirects: bool = False,
150
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
151
verify: ssl.SSLContext | str | bool = True,
152
trust_env: bool = True,
153
) -> Response:
154
"""Send a DELETE request."""
155
156
def head(
157
url: URL | str,
158
*,
159
params: QueryParamTypes | None = None,
160
headers: HeaderTypes | None = None,
161
cookies: CookieTypes | None = None,
162
auth: AuthTypes | None = None,
163
proxy: ProxyTypes | None = None,
164
follow_redirects: bool = False,
165
verify: ssl.SSLContext | str | bool = True,
166
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
167
trust_env: bool = True,
168
) -> Response:
169
"""Send a HEAD request."""
170
171
def options(
172
url: URL | str,
173
*,
174
params: QueryParamTypes | None = None,
175
headers: HeaderTypes | None = None,
176
cookies: CookieTypes | None = None,
177
auth: AuthTypes | None = None,
178
proxy: ProxyTypes | None = None,
179
follow_redirects: bool = False,
180
verify: ssl.SSLContext | str | bool = True,
181
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
182
trust_env: bool = True,
183
) -> Response:
184
"""Send an OPTIONS request."""
185
186
def request(
187
method: str,
188
url: URL | str,
189
*,
190
params: QueryParamTypes | None = None,
191
content: RequestContent | None = None,
192
data: RequestData | None = None,
193
files: RequestFiles | None = None,
194
json: Any | None = None,
195
headers: HeaderTypes | None = None,
196
cookies: CookieTypes | None = None,
197
auth: AuthTypes | None = None,
198
proxy: ProxyTypes | None = None,
199
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
200
follow_redirects: bool = False,
201
verify: ssl.SSLContext | str | bool = True,
202
trust_env: bool = True,
203
) -> Response:
204
"""Send an HTTP request with specified method."""
205
```
206
207
[Request Functions API](./requests-api.md)
208
209
### Synchronous HTTP Client
210
211
The `Client` class provides a synchronous HTTP client with connection pooling, cookie persistence, and configuration reuse across multiple requests.
212
213
```python { .api }
214
class Client:
215
def __init__(
216
self,
217
*,
218
auth: AuthTypes | None = None,
219
params: QueryParamTypes | None = None,
220
headers: HeaderTypes | None = None,
221
cookies: CookieTypes | None = None,
222
verify: ssl.SSLContext | str | bool = True,
223
cert: CertTypes | None = None,
224
trust_env: bool = True,
225
http1: bool = True,
226
http2: bool = False,
227
proxy: ProxyTypes | None = None,
228
mounts: None | Mapping[str, BaseTransport | None] = None,
229
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
230
follow_redirects: bool = False,
231
limits: Limits = DEFAULT_LIMITS,
232
max_redirects: int = DEFAULT_MAX_REDIRECTS,
233
event_hooks: None | Mapping[str, list[EventHook]] = None,
234
base_url: URL | str = "",
235
transport: BaseTransport | None = None,
236
default_encoding: str | Callable[[bytes], str] = "utf-8",
237
) -> None:
238
"""Initialize a synchronous HTTP client."""
239
240
def get(
241
self,
242
url: URL | str,
243
*,
244
params: QueryParamTypes | None = None,
245
headers: HeaderTypes | None = None,
246
cookies: CookieTypes | None = None,
247
auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
248
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
249
timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
250
extensions: RequestExtensions | None = None,
251
) -> Response:
252
"""Send a GET request."""
253
254
def post(
255
self,
256
url: URL | str,
257
*,
258
content: RequestContent | None = None,
259
data: RequestData | None = None,
260
files: RequestFiles | None = None,
261
json: Any | None = None,
262
params: QueryParamTypes | None = None,
263
headers: HeaderTypes | None = None,
264
cookies: CookieTypes | None = None,
265
auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
266
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
267
timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
268
extensions: RequestExtensions | None = None,
269
) -> Response:
270
"""Send a POST request."""
271
272
def request(
273
self,
274
method: str,
275
url: URL | str,
276
*,
277
content: RequestContent | None = None,
278
data: RequestData | None = None,
279
files: RequestFiles | None = None,
280
json: Any | None = None,
281
params: QueryParamTypes | None = None,
282
headers: HeaderTypes | None = None,
283
cookies: CookieTypes | None = None,
284
auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
285
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
286
timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
287
extensions: RequestExtensions | None = None,
288
) -> Response:
289
"""Send an HTTP request."""
290
291
def send(
292
self,
293
request: Request,
294
*,
295
stream: bool = False,
296
auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
297
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
298
timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
299
) -> Response:
300
"""Send a pre-built Request object."""
301
302
def close(self) -> None:
303
"""Close the client and release connections."""
304
```
305
306
[Synchronous Client API](./sync-client.md)
307
308
### Asynchronous HTTP Client
309
310
The `AsyncClient` class provides an asynchronous HTTP client with the same features as the synchronous client but using async/await syntax.
311
312
```python { .api }
313
class AsyncClient:
314
def __init__(
315
self,
316
*,
317
auth: AuthTypes | None = None,
318
params: QueryParamTypes | None = None,
319
headers: HeaderTypes | None = None,
320
cookies: CookieTypes | None = None,
321
verify: ssl.SSLContext | str | bool = True,
322
cert: CertTypes | None = None,
323
trust_env: bool = True,
324
http1: bool = True,
325
http2: bool = False,
326
proxy: ProxyTypes | None = None,
327
mounts: None | Mapping[str, AsyncBaseTransport | None] = None,
328
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
329
follow_redirects: bool = False,
330
limits: Limits = DEFAULT_LIMITS,
331
max_redirects: int = DEFAULT_MAX_REDIRECTS,
332
event_hooks: None | Mapping[str, list[EventHook]] = None,
333
base_url: URL | str = "",
334
transport: AsyncBaseTransport | None = None,
335
default_encoding: str | Callable[[bytes], str] = "utf-8",
336
) -> None:
337
"""Initialize an asynchronous HTTP client."""
338
339
async def get(
340
self,
341
url: URL | str,
342
*,
343
params: QueryParamTypes | None = None,
344
headers: HeaderTypes | None = None,
345
cookies: CookieTypes | None = None,
346
auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
347
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
348
timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
349
extensions: RequestExtensions | None = None,
350
) -> Response:
351
"""Send a GET request."""
352
353
async def post(
354
self,
355
url: URL | str,
356
*,
357
content: RequestContent | None = None,
358
data: RequestData | None = None,
359
files: RequestFiles | None = None,
360
json: Any | None = None,
361
params: QueryParamTypes | None = None,
362
headers: HeaderTypes | None = None,
363
cookies: CookieTypes | None = None,
364
auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
365
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
366
timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
367
extensions: RequestExtensions | None = None,
368
) -> Response:
369
"""Send a POST request."""
370
371
async def request(
372
self,
373
method: str,
374
url: URL | str,
375
*,
376
content: RequestContent | None = None,
377
data: RequestData | None = None,
378
files: RequestFiles | None = None,
379
json: Any | None = None,
380
params: QueryParamTypes | None = None,
381
headers: HeaderTypes | None = None,
382
cookies: CookieTypes | None = None,
383
auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
384
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
385
timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
386
extensions: RequestExtensions | None = None,
387
) -> Response:
388
"""Send an HTTP request."""
389
390
async def aclose(self) -> None:
391
"""Close the client and release connections."""
392
```
393
394
[Asynchronous Client API](./async-client.md)
395
396
### Response and Request Objects
397
398
Core data model classes for representing HTTP requests and responses.
399
400
```python { .api }
401
class Response:
402
status_code: int
403
headers: Headers
404
content: bytes
405
text: str
406
url: URL
407
request: Request
408
409
def json(self, **kwargs: Any) -> Any:
410
"""Parse response content as JSON."""
411
412
def raise_for_status(self) -> None:
413
"""Raise HTTPStatusError for 4xx/5xx status codes."""
414
415
class Request:
416
method: str
417
url: URL
418
headers: Headers
419
content: bytes
420
421
def read(self):
422
"""Read the request content."""
423
424
class Headers:
425
"""Case-insensitive HTTP headers."""
426
427
def get(self, key, default=None):
428
"""Get header value."""
429
```
430
431
[Core Types API](./types.md)
432
433
### Authentication
434
435
Authentication mechanisms for HTTP requests including Basic, Digest, and custom authentication.
436
437
```python { .api }
438
class BasicAuth:
439
def __init__(self, username, password):
440
"""HTTP Basic authentication."""
441
442
class DigestAuth:
443
def __init__(self, username, password):
444
"""HTTP Digest authentication."""
445
446
class Auth:
447
"""Base class for custom authentication."""
448
449
def auth_flow(self, request):
450
"""Authentication flow generator."""
451
```
452
453
[Authentication API](./authentication.md)
454
455
### Configuration
456
457
Timeout, connection limits, proxy, and SSL configuration options.
458
459
```python { .api }
460
class Timeout:
461
def __init__(self, timeout=5.0, *, connect=None, read=None, write=None, pool=None):
462
"""Configure request timeouts."""
463
464
class Limits:
465
def __init__(self, *, max_connections=100, max_keepalive_connections=20, keepalive_expiry=5.0):
466
"""Configure connection pool limits."""
467
468
class Proxy:
469
def __init__(self, url, *, auth=None, headers=None):
470
"""Configure HTTP/HTTPS/SOCKS proxy."""
471
```
472
473
[Configuration API](./configuration.md)
474
475
### Exception Handling
476
477
Comprehensive exception hierarchy for handling different types of HTTP errors and request failures.
478
479
```python { .api }
480
class HTTPError(Exception):
481
"""Base class for all HTTP-related exceptions."""
482
483
@property
484
def request(self) -> Request:
485
"""The request that caused this exception."""
486
487
class RequestError(HTTPError):
488
"""Exception occurred during request processing."""
489
490
class HTTPStatusError(HTTPError):
491
"""Response returned an HTTP error status code (4xx or 5xx)."""
492
493
@property
494
def response(self) -> Response:
495
"""The response that caused this exception."""
496
497
# Transport layer exceptions
498
class TransportError(RequestError):
499
"""Exception occurred at the transport layer."""
500
501
class TimeoutException(TransportError):
502
"""Request timed out."""
503
504
class ConnectTimeout(TimeoutException):
505
"""Connection timed out."""
506
507
class ReadTimeout(TimeoutException):
508
"""Reading response timed out."""
509
510
class WriteTimeout(TimeoutException):
511
"""Writing request timed out."""
512
513
class PoolTimeout(TimeoutException):
514
"""Connection pool timeout."""
515
516
class NetworkError(TransportError):
517
"""Network-related error."""
518
519
class ConnectError(NetworkError):
520
"""Failed to establish connection."""
521
522
class ReadError(NetworkError):
523
"""Error reading response."""
524
525
class WriteError(NetworkError):
526
"""Error writing request."""
527
528
class CloseError(NetworkError):
529
"""Error closing connection."""
530
531
class ProtocolError(TransportError):
532
"""HTTP protocol error."""
533
534
class LocalProtocolError(ProtocolError):
535
"""Local protocol error."""
536
537
class RemoteProtocolError(ProtocolError):
538
"""Remote protocol error."""
539
540
class ProxyError(TransportError):
541
"""Proxy-related error."""
542
543
class UnsupportedProtocol(TransportError):
544
"""Unsupported protocol."""
545
546
class DecodingError(RequestError):
547
"""Response content decoding error."""
548
549
class TooManyRedirects(RequestError):
550
"""Too many redirect responses."""
551
552
# URL and data validation exceptions
553
class InvalidURL(Exception):
554
"""Invalid URL format."""
555
556
class CookieConflict(Exception):
557
"""Cookie conflict error."""
558
559
# Streaming exceptions
560
class StreamError(Exception):
561
"""Stream-related error."""
562
563
class StreamConsumed(StreamError):
564
"""Stream content already consumed."""
565
566
class StreamClosed(StreamError):
567
"""Stream is closed."""
568
569
class ResponseNotRead(StreamError):
570
"""Response content not read."""
571
572
class RequestNotRead(StreamError):
573
"""Request content not read."""
574
```
575
576
### Streaming
577
578
Stream request and response content to handle large files efficiently.
579
580
```python { .api }
581
def stream(
582
method: str,
583
url: URL | str,
584
*,
585
params: QueryParamTypes | None = None,
586
content: RequestContent | None = None,
587
data: RequestData | None = None,
588
files: RequestFiles | None = None,
589
json: Any | None = None,
590
headers: HeaderTypes | None = None,
591
cookies: CookieTypes | None = None,
592
auth: AuthTypes | None = None,
593
proxy: ProxyTypes | None = None,
594
timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
595
follow_redirects: bool = False,
596
verify: ssl.SSLContext | str | bool = True,
597
trust_env: bool = True,
598
) -> Iterator[Response]:
599
"""Stream a request response."""
600
601
class Response:
602
def iter_bytes(self, chunk_size: int = 1024) -> Iterator[bytes]:
603
"""Iterate over response content as bytes."""
604
605
def iter_text(self, chunk_size: int = 1024) -> Iterator[str]:
606
"""Iterate over response content as text."""
607
```
608
609
[Streaming API](./streaming.md)