winhttp
Safe, ergonomic Rust bindings for the Windows WinHTTP API.
This crate lets you make HTTP requests on Windows without pulling in a large third-party HTTP stack. It talks directly to the operating system through WinHTTP, so your binaries stay small and you get automatic access to system proxy settings, TLS, and HTTP/2 for free.
Both synchronous and asynchronous requests are supported. The async API is runtime-agnostic, meaning it works with tokio, smol, pollster, or any other executor you prefer.
Use case
Suppose you are building a Windows desktop tool that periodically checks an internal API for updates. You want something lightweight that respects corporate proxy settings out of the box and does not drag in OpenSSL or a bundled TLS library.
use Client;
If you only need a single one-off request, the module-level helpers make it even shorter:
let resp = get?;
println!;
Features
The library is organized in layers so you can choose the level of control you need.
High-level client. The Client type offers one-liner methods for GET, POST, PUT, DELETE, PATCH, and HEAD. It handles connection pooling, URL resolution against a configurable base URL, and a builder pattern for custom headers and bodies.
Async support. Enable the async feature to unlock async_get, async_post, and friends. These return standard Futures that work with any executor. There is no hidden runtime—just wire them up to whatever you already use.
[]
= { = "0.1", = ["async"] }
// Works with tokio, smol, pollster, or anything else.
let resp = client.async_get.await?;
JSON deserialization. Enable the json feature to call resp.json::<T>() and get your response body deserialized through serde in one step.
JSON request bodies. The same json feature also provides Body::json, which serializes a struct into JSON and sets the Content-Type header automatically. Every method that accepts a body (post, put, patch, and the builder's .body()) takes impl Into<Body>, so you can pass raw bytes or a Body::json value interchangeably.
[]
= { = "0.1", = ["async", "json"] }
use ;
use ;
Raw bytes still work everywhere a Body is expected:
client.post?;
client.post?;
Low-level access. The Session, Connection, and Request types are thin wrappers around the raw WinHTTP handles. They give you full control over protocol flags, TLS settings, decompression, redirect policies, and authentication schemes while still handling resource cleanup automatically.
WebSocket. Enable the websocket feature to get synchronous and asynchronous WebSocket support. The WebSocket type upgrades an HTTP connection and provides typed send and receive operations. With both websocket and async enabled, AsyncWebSocket adds future-based send/receive, graceful close, and a futures_core::Stream adapter for reading messages in a loop.
[]
= { = "0.1", = ["websocket"] }
use *;
Proxy detection. Built-in helpers read the system proxy configuration, detect auto-proxy URLs, and resolve proxies for specific URLs, matching the behavior that browsers and other Windows applications use.
Type-safe flags. Methods that accept raw u32 flags also have _typed() variants that use strongly-typed wrappers like AuthScheme, SecurityFlags, SecureProtocol, and DecompressionFlags. This prevents mixing up unrelated flag values at compile time.
Feature flags
| Feature | Default | Description |
|---|---|---|
async |
No | Enables async HTTP methods via crossfire channels. Runtime-agnostic. |
json |
No | Adds Response::json for deserializing and Body::json for serializing via serde. |
websocket |
No | Enables WebSocket and AsyncWebSocket for upgrading HTTP connections to WebSocket. |
Requirements
This crate only works on Windows. It requires Rust 1.85 or later.
Examples
The repository includes several runnable examples.
# Synchronous low-level request
# Async with tokio
# Async with smol
# High-level client helpers
# Feature demo (HTTP/2, decompression, redirects)
# Async GET with pollster
# Async with JSON request/response bodies
# Sync + async WebSocket echo
License
See the license file in the repository for details.