Packages
hackney
4.2.0
4.7.2
4.7.1
4.7.0
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.5
4.4.3
4.4.2
4.4.1
4.4.0
4.3.0
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.3
4.0.2
4.0.1
4.0.0
3.2.1
3.2.0
3.1.2
3.1.1
3.1.0
3.0.3
3.0.2
3.0.1
3.0.0
retired
2.0.1
2.0.0
2.0.0-beta.1
1.25.0
1.24.1
1.24.0
1.23.0
1.22.0
1.21.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.0
1.15.2
1.15.1
1.15.0
1.14.3
1.14.2
1.14.0
1.13.0
1.12.1
1.12.0
1.11.0
1.10.1
1.10.0
1.9.0
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.0
1.7.1
1.7.0
1.6.6
retired
1.6.5
1.6.4
retired
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.6
1.0.5
1.0.2
1.0.1
0.15.2
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support
Current section
Files
Jump to
Current section
Files
README.md
# hackney
An HTTP client for Erlang. Simple, reliable, fast.
[](https://github.com/benoitc/hackney/actions?query=workflow%3Abuild)
[](https://hex.pm/packages/hackney)
## Why hackney?
- **HTTP/3 support** - Experimental QUIC/HTTP3 via pure Erlang. Opt-in with `{protocols, [http3, http2, http1]}`.
- **HTTP/2 support** - Automatic protocol negotiation via ALPN. Multiplexing, header compression, flow control.
- **Process per connection** - Each connection runs in its own `gen_statem` process. Clean isolation, automatic cleanup on crashes.
- **Connection pooling** - Reuse connections automatically. Configure pools per host or globally.
- **Streaming** - Stream request bodies, response bodies, or both. Handle large files without loading them in memory.
- **Async responses** - Get response chunks as messages. Process other work while waiting.
- **WebSocket support** - Full WebSocket client with the same process-per-connection model.
- **WebTransport support** - WebTransport client over HTTP/3 (or HTTP/2) with a WebSocket-shaped API; switch by swapping the `ws_` prefix for `wt_`.
- **IPv6 first** - Happy Eyeballs algorithm tries IPv6 before IPv4 for faster connections on modern networks.
- **SSL by default** - Secure connections with certificate verification using Mozilla's CA bundle.
- **Automatic decompression** - Transparently decompress gzip/deflate responses with `{auto_decompress, true}`.
## Quick Start
```erlang
%% Start hackney
application:ensure_all_started(hackney).
%% Simple GET - the body is returned directly
{ok, 200, _Headers, Body} = hackney:get(<<"https://httpbin.org/get">>).
%% POST JSON
Headers = [{<<"content-type">>, <<"application/json">>}],
Payload = <<"{\"key\": \"value\"}">>,
{ok, 200, _, _} = hackney:post(<<"https://httpbin.org/post">>, Headers, Payload).
```
## Installation
### Rebar3
```erlang
{deps, [hackney]}.
```
### Mix
```elixir
{:hackney, "~> 4.0"}
```
## Documentation
| Guide | Description |
|-------|-------------|
| [Getting Started](GETTING_STARTED.md) | Installation, first requests, basic patterns |
| [HTTP Guide](guides/http_guide.md) | Requests, responses, streaming, async, pools |
| [HTTP/2 Guide](guides/http2_guide.md) | HTTP/2 protocol, ALPN, multiplexing, flow control |
| [HTTP/3 Guide](guides/http3_guide.md) | HTTP/3 over QUIC, opt-in configuration, Alt-Svc |
| [WebSocket Guide](guides/websocket_guide.md) | Connect, send, receive, active mode |
| [WebTransport Guide](guides/webtransport_guide.md) | Streams, datagrams, multiplexing, server handlers |
| [Design Guide](guides/design.md) | Architecture, pooling, load regulation internals |
| [Migration Guide](guides/MIGRATION.md) | Upgrading from hackney 1.x |
| [API Reference](https://hexdocs.pm/hackney) | Full module documentation |
| [Changelog](NEWS.md) | Version history |
## Features
### HTTP Methods
All standard HTTP methods as convenient functions:
```erlang
hackney:get(URL).
hackney:post(URL, Headers, Body).
hackney:put(URL, Headers, Body).
hackney:delete(URL).
hackney:head(URL).
hackney:options(URL).
hackney:patch(URL, Headers, Body).
```
### Connection Pooling
Connections are pooled by default. Configure pools for different use cases:
```erlang
%% Use default pool
hackney:get(URL).
%% Named pool with custom settings
hackney_pool:start_pool(api_pool, [{max_connections, 100}]),
hackney:get(URL, [], <<>>, [{pool, api_pool}]).
%% No pooling for one-off requests
hackney:get(URL, [], <<>>, [{pool, false}]).
```
### Streaming
Stream request bodies for uploads:
```erlang
{ok, Ref} = hackney:post(URL, Headers, stream),
hackney:send_body(Ref, <<"chunk 1">>),
hackney:send_body(Ref, <<"chunk 2">>),
hackney:finish_send_body(Ref),
{ok, Status, _, Ref} = hackney:start_response(Ref),
{ok, Body} = hackney:body(Ref).
```
Sync responses return the full body directly. To receive a large response
piece-by-piece, use the async API (see the [Async Responses](#async-responses)
section below).
### Async Responses
Receive response data as messages:
```erlang
{ok, Ref} = hackney:get(URL, [], <<>>, [async]),
receive
{hackney_response, Ref, {status, 200, _}} -> ok
end,
receive
{hackney_response, Ref, {headers, Headers}} -> ok
end,
receive_body(Ref).
receive_body(Ref) ->
receive
{hackney_response, Ref, done} -> ok;
{hackney_response, Ref, Bin} -> receive_body(Ref)
end.
```
### WebSocket
```erlang
{ok, Conn} = hackney:ws_connect(<<"wss://echo.websocket.org">>),
ok = hackney:ws_send(Conn, {text, <<"hello">>}),
{ok, {text, <<"hello">>}} = hackney:ws_recv(Conn),
hackney:ws_close(Conn).
```
### WebTransport
Same shape as WebSocket, over HTTP/3 (QUIC). Swap `ws_` for `wt_`:
```erlang
{ok, Conn} = hackney:wt_connect(<<"https://example.com/wt">>),
ok = hackney:wt_send(Conn, {binary, <<"hello">>}),
{ok, {binary, <<"hello">>}} = hackney:wt_recv(Conn),
hackney:wt_close(Conn).
```
### HTTP/2
HTTP/2 is used automatically when the server supports it:
```erlang
%% Automatic HTTP/2 via ALPN negotiation
{ok, 200, Headers, Body} = hackney:get(<<"https://nghttp2.org/">>).
%% Force HTTP/1.1 only
hackney:get(URL, [], <<>>, [{protocols, [http1]}]).
%% Force HTTP/2 only
hackney:get(URL, [], <<>>, [{protocols, [http2]}]).
```
### HTTP/3 (Experimental)
HTTP/3 support is **opt-in**. Enable it per-request or globally:
```erlang
%% Enable HTTP/3 for a single request
hackney:get(URL, [], <<>>, [{protocols, [http3, http2, http1]}]).
%% Enable HTTP/3 globally (application-wide)
application:set_env(hackney, default_protocols, [http3, http2, http1]).
```
IPv6 works out of the box (Happy Eyeballs); force a family with
`{connect_options, [{family, inet6}]}`. Session resumption and 0-RTT are on by
default and cached per host; disable with `{zero_rtt, false}`. See the
[HTTP/3 Guide](guides/http3_guide.md) for details.
**Note:** HTTP/3 uses QUIC (UDP transport). Some networks may block UDP traffic.
### Multipart
Upload files and form data:
```erlang
Multipart = {multipart, [
{<<"field">>, <<"value">>},
{file, <<"/path/to/file.txt">>},
{file, <<"/path/to/image.png">>, <<"image.png">>, [{<<"content-type">>, <<"image/png">>}]}
]},
hackney:post(URL, [], Multipart).
```
### Proxy Support
```erlang
%% HTTP proxy
hackney:get(URL, [], <<>>, [{proxy, <<"http://proxy:8080">>}]).
%% With authentication
hackney:get(URL, [], <<>>, [{proxy, <<"http://user:pass@proxy:8080">>}]).
%% Environment variables work automatically
%% HTTP_PROXY, HTTPS_PROXY, NO_PROXY
```
### Redirects
```erlang
%% Follow redirects automatically
hackney:get(URL, [], <<>>, [{follow_redirect, true}, {max_redirect, 5}]).
```
### Timeouts
```erlang
hackney:get(URL, [], <<>>, [
{connect_timeout, 5000}, %% Connection timeout
{recv_timeout, 30000} %% Response timeout
]).
```
### Automatic Decompression
```erlang
%% Automatically decompress gzip/deflate responses
hackney:get(URL, [], <<>>, [{auto_decompress, true}]).
```
### SSL Options
```erlang
%% Custom CA certificate
hackney:get(URL, [], <<>>, [
{ssl_options, [{cacertfile, "/path/to/ca.pem"}]}
]).
%% Skip verification (development only)
hackney:get(URL, [], <<>>, [insecure]).
```
## Modules
| Module | Purpose |
|--------|---------|
| `hackney` | Main API - requests, connections, WebSocket |
| `hackney_pool` | Connection pool management |
| `hackney_url` | URL parsing and encoding |
| `hackney_headers` | Header manipulation |
| `hackney_multipart` | Multipart encoding |
| `hackney_cookie` | Cookie parsing |
| `hackney_http` | HTTP protocol parser |
## Requirements
Erlang/OTP 27+
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on pull requests and development setup.
Issues and pull requests welcome at https://github.com/benoitc/hackney
## Support
hackney is critical infrastructure for many Erlang and Elixir applications. If your company relies on it, consider sponsoring its maintenance:
[](https://github.com/sponsors/benoitc)
Sponsorship ensures continued development, timely security patches, and compatibility with OTP releases.
**Corporate sponsors:** If hackney is part of your infrastructure, [reach out](mailto:benoitc@enki-multimedia.eu) for sponsored support options.
## Sponsors
<a href="https://enki-multimedia.eu"><img src="guides/images/enki-multimedia.svg" alt="Enki Multimedia" height="50" /></a>
## License
Apache 2.0 - See [LICENSE](LICENSE) and [NOTICE](NOTICE)
Copyright (c) 2012-2026 Benoit Chesneau