
Product
Introducing Socket Firewall Enterprise: Flexible, Configurable Protection for Modern Package Ecosystems
Socket Firewall Enterprise is now available with flexible deployment, configurable policies, and expanded language support.
Do one thing, and do it well.
The HTTP Core package provides a minimal low-level HTTP client, which does one thing only. Sending HTTP requests.
It does not provide any high level model abstractions over the API, does not handle redirects, multipart uploads, building authentication headers, transparent HTTP caching, URL parsing, session cookie handling, content or charset decoding, handling JSON, environment based configuration defaults, or any of that Jazz.
Some things HTTP Core does do:
asyncio and trio.Python 3.8+
For HTTP/1.1 only support, install with:
$ pip install httpcore
There are also a number of optional extras available...
$ pip install httpcore['asyncio,trio,http2,socks']
Send an HTTP request:
import httpcore
response = httpcore.request("GET", "https://www.example.com/")
print(response)
# <Response [200]>
print(response.status)
# 200
print(response.headers)
# [(b'Accept-Ranges', b'bytes'), (b'Age', b'557328'), (b'Cache-Control', b'max-age=604800'), ...]
print(response.content)
# b'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>\n\n<meta charset="utf-8"/>\n ...'
The top-level httpcore.request() function is provided for convenience. In practice whenever you're working with httpcore you'll want to use the connection pooling functionality that it provides.
import httpcore
http = httpcore.ConnectionPool()
response = http.request("GET", "https://www.example.com/")
Once you're ready to get going, head over to the documentation.
You probably don't want to be using HTTP Core directly. It might make sense if
you're writing something like a proxy service in Python, and you just want
something at the lowest possible level, but more typically you'll want to use
a higher level client library, such as httpx.
The motivation for httpcore is:
The httpcore package has the following dependencies...
h11certifiAnd the following optional extras...
anyio - Required by pip install httpcore['asyncio'].trio - Required by pip install httpcore['trio'].h2 - Required by pip install httpcore['http2'].socksio - Required by pip install httpcore['socks'].We use SEMVER for our versioning policy.
For changes between package versions please see our project changelog.
We recommend pinning your requirements either the most current major version, or a more specific version range:
pip install 'httpcore==1.*'
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
AttributeError when importing on Python 3.14. (#1005)proxy=… configuration on ConnectionPool(). (#974)trio dependency pinning. (#956)trio raising NotImplementedError on unsupported platforms. (#955)ssl.SSLError to httpcore.ConnectError. (#918)EndOfStream exception for anyio backend. (#899)0.25.* series in package dependancies. (#903)target request extension. (#888)Upgrade and CONNECT when some data in the stream has been read. (#882)float("inf") timeouts in Event.wait function. (#846)From version 1.0 our async support is now optional, as the package has minimal dependencies by default.
For async support use either pip install 'httpcore[asyncio]' or pip install 'httpcore[trio]'.
The project versioning policy is now explicitly governed by SEMVER. See https://semver.org/.
sni_hostname extension with SOCKS proxy. (#774)Extensions from Mapping[Str, Any] to MutableMapping[Str, Any]. (#762)trace callback is passed to an asynchronous request or an asynchronous trace callback is passed to a synchronous request. (#717)socket_options argument to ConnectionPool and HTTProxy classes. (#668)sni_hostname request extension. (#696)anyio package. (#692)retries option to SOCKS proxy classes. (#643)ws and wss schemes. Allows us to properly support websocket upgrade connections. (#625)RuntimeError when closing a connection pool with active connections. Removes some error cases when cancellations are used. (#631)anyio, so that it's no longer a hard dependancy, and isn't imported if unused. (#639)RuntimeError if attempting to us UNIX domain sockets on Windows. (#619)h11 0.14. (#579)timeout configuration. (#506)typing.Optional for type hints. (#513)trio map OSError exceptions to ConnectError. (#543)http:// URLs. (#492)max_connections becomes optional. (Pull #429)certifi is now included in the install dependancies. (Pull #428)h2 is now strictly optional. (Pull #428)The 0.14 release is a complete reworking of httpcore, comprehensively addressing some underlying issues in the connection pooling, as well as substantially redesigning the API to be more user friendly.
Some of the lower-level API design also makes the components more easily testable in isolation, and the package now has 100% test coverage.
See discussion #419 for a little more background.
There's some other neat bits in there too, such as the "trace" extension, which gives a hook into inspecting the internal events that occur during the request/response cycle. This extension is needed for the HTTPX cli, in order to...
Note that curio support is not currently available in 0.14.0. If you're using httpcore with curio please get in touch, so we can assess if we ought to prioritize it as a feature or not.
anyio as the default backend implementation when running with asyncio. Resolves some awkward TLS timeout issues.httpcore.SyncConnectionPool(http1=False). (Pull #333)select.poll support. (Pull #331)RemoteProtocolError where server disconnects without sending a response. (Pull #313)The 0.13 release updates the core API in order to match the HTTPX Transport API, introduced in HTTPX 0.18 onwards.
An example of making requests with the new interface is:
with httpcore.SyncConnectionPool() as http:
status_code, headers, stream, extensions = http.handle_request(
method=b'GET',
url=(b'https', b'example.org', 443, b'/'),
headers=[(b'host', b'example.org'), (b'user-agent', b'httpcore')]
stream=httpcore.ByteStream(b''),
extensions={}
)
body = stream.read()
print(status_code, body)
.request() method is now handle_request(). (Pull #296).arequest() method is now .handle_async_request(). (Pull #296)headers argument is no longer optional. (Pull #296)stream argument is no longer optional. (Pull #296)ext argument is now named extensions, and is no longer optional. (Pull #296)"reason" extension keyword is now named "reason_phrase". (Pull #296)"reason_phrase" and "http_version" extensions now use byte strings for their values. (Pull #296)httpcore.PlainByteStream() class becomes httpcore.ByteStream(). (Pull #296).read() interface. (Pull #296)asyncio. (Pull #167)anyio backend. (Pull #236)Host header precedence for :authority in HTTP/2. (Pull #241, #243)asyncio. (Pull #242, #244)asyncio SSL warning when using proxy tunneling. (Pull #249)ImportError occurring on Python 3.9 when using the HTTP/1.1 sync client in a multithreaded context. (Pull #237)trio. (Pull #225)The Transport API with 0.11.0 has a couple of significant changes.
Firstly we've moved changed the request interface in order to allow extensions, which will later enable us to support features such as trailing headers, HTTP/2 server push, and CONNECT/Upgrade connections.
The interface changes from:
def request(method, url, headers, stream, timeout):
return (http_version, status_code, reason, headers, stream)
To instead including an optional dictionary of extensions on the request and response:
def request(method, url, headers, stream, ext):
return (status_code, headers, stream, ext)
Having an open-ended extensions point will allow us to add later support for various optional features, that wouldn't otherwise be supported without these API changes.
In particular:
Currently extensions are limited to:
timeout - Optional. Timeout dictionary.http_version - Optional. Include the HTTP version used on the response.reason - Optional. Include the reason phrase used on the response. Only valid with HTTP/1.*.See https://github.com/encode/httpx/issues/1274#issuecomment-694884553 for the history behind this.
Secondly, the async version of request is now namespaced as arequest.
This allows concrete transports to support both sync and async implementations on the same class.
backend="anyio". (Pull #169).request and .arequest so implementations can support both sync and async. (Pull #189)max_keepalive_connections configuration. (Pull #153)max_keepalive_connections on AsyncHTTPProxy/SyncHTTPProxy classes.The most notable change in the 0.10.0 release is that HTTP/2 support is now fully optional.
Use either pip install httpcore for HTTP/1.1 support only, or pip install httpcore[http2] for HTTP/1.1 and HTTP/2 support.
local_address=... support. (Pull #100, #134)PlainByteStream, IteratorByteStream, AsyncIteratorByteStream. The AsyncByteSteam and SyncByteStream classes are now pure interface classes. (#133)LocalProtocolError, RemoteProtocolError exceptions. (Pull #129)UnsupportedProtocol exception. (Pull #128).get_connection_info() method. (Pull #102, #137)max_keepalive is deprecated in favour of max_keepalive_connections. (Pull #140)Optional[int] instead of int. (Pull #92)Host and Accept headers on proxy "CONNECT" requests.httpcore.AsyncByteStream, httpcore.SyncByteStream without type conflicts.###Â Added
TimeoutException base class.FAQs
A minimal low-level HTTP client.
We found that httpcore demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket Firewall Enterprise is now available with flexible deployment, configurable policies, and expanded language support.

Security News
Open source dashboard CNAPulse tracks CVE Numbering Authorities’ publishing activity, highlighting trends and transparency across the CVE ecosystem.

Product
Detect malware, unsafe data flows, and license issues in GitHub Actions with Socket’s new workflow scanning support.