Hurl

A command-line tool that runs HTTP requests defined in plain text format, making it easy to test APIs, chain requests, and assert on responses.

Screenshot of Hurl

Hurl is a command-line tool for running and testing HTTP requests defined in a simple, human-readable plain text format. A .hurl file describes one or more HTTP requests along with assertions about the responses — status codes, headers, body content, JSON values, XPath expressions, and more. It's equally at home as a quick API scratchpad and as a rigorous integration test suite in CI.

Features

  • Plain text format — requests and assertions live in a .hurl file that is readable, diffable, and easy to commit alongside your code
  • Chaining — multiple requests in a single file run in sequence; values captured from one response (e.g. a token) can be injected into the next request
  • Rich assertions — assert on status code, response headers, JSON values (via JSONPath), XML values (via XPath), regex matches, body content, and more
  • Variables — parameterise requests with --variable flags or .env files for different environments
  • HTML and JSON reports — generate test reports suitable for CI dashboards
  • Parallel execution — run multiple .hurl files in parallel with --parallel
  • Cookie handling — automatically manages cookies across requests in a session
  • Fast — built in Rust on top of libcurl, with minimal overhead
  • No runtime dependencies — a single binary handles everything

Installation

cargo install hurl

Or via your system package manager:

# macOS
brew install hurl

# Arch Linux
pacman -S hurl

# Debian / Ubuntu (Debian 12+)
apt install hurl

# Fedora
dnf install hurl

Pre-built .deb and .rpm packages are also available on the releases page.

Pre-built binaries for all major platforms are available on the releases page.

File Format

A .hurl file contains one or more HTTP request/response pairs:

# A simple GET request
GET https://httpbin.org/get

HTTP 200
[Asserts]
header "Content-Type" contains "application/json"
jsonpath "$.url" == "https://httpbin.org/get"

Multiple requests chain together in a single file:

# Step 1: Log in and capture the token
POST https://api.example.com/auth/login
Content-Type: application/json
{
  "username": "alice",
  "password": "s3cret"
}

HTTP 200
[Captures]
token: jsonpath "$.access_token"

# Step 2: Use the captured token in the next request
GET https://api.example.com/users/me
Authorization: Bearer {{token}}

HTTP 200
[Asserts]
jsonpath "$.username" == "alice"
jsonpath "$.email" isString

Usage

# Run a single .hurl file
hurl api.hurl

# Run with verbose output (shows full request/response)
hurl --verbose api.hurl

# Run and treat assertion failures as a non-zero exit code (for CI)
hurl --test api.hurl

# Run all .hurl files in a directory
hurl --test tests/*.hurl

# Run files in parallel
hurl --test --parallel tests/*.hurl

# Pass variables (e.g. for different environments)
hurl --variable base_url=https://staging.example.com api.hurl

# Load variables from a file
hurl --variables-file .env.staging api.hurl

# Generate an HTML report
hurl --test --report-html report/ tests/*.hurl

# Generate a JUnit XML report (for CI)
hurl --test --report-junit report.xml tests/*.hurl

Assertions

Hurl supports a rich set of assertion types:

GET https://api.example.com/products

HTTP 200
[Asserts]
# Status and timing
status == 200
duration < 500                          # response time in ms

# Headers
header "Content-Type" == "application/json; charset=utf-8"
header "X-RateLimit-Remaining" toInteger greaterThan 0

# JSONPath
jsonpath "$.products" isCollection
jsonpath "$.products" count == 10
jsonpath "$.products[0].name" isString
jsonpath "$.products[0].price" greaterThan 0.0

# Regex on the body
body matches /products.*available/

# XPath (for XML/HTML responses)
xpath "//title/text()" == "Products"

Why not just use curl or Postman?

curl is excellent for one-off requests but gets unwieldy for chained workflows, variable substitution, and structured assertions. Postman and similar GUI tools work well interactively but don't version-control well and add friction to CI pipelines. Hurl occupies a sweet spot: plain text files that live in your repo, run from the command line, and integrate naturally into any CI system.