Testing RESTful APIs, GraphQL endpoints, and Web services from the Linux terminal often involves choosing between two extremes: writing complex curl shell scripts packed with fragile jq pipes, or setting up heavyweight, GUI-reliant tools like Postman. While curl is exceptional for one-off requests, chaining multi-step API workflows—such as authenticating via OAuth, capturing a bearer token, and asserting HTTP response status codes—quickly becomes messy in standard Bash.
Hurl bridges this gap. Powered by libcurl and written in Rust, Hurl is a command-line tool that executes HTTP requests defined in simple, human-readable plain-text files. It allows developers and system administrators to chain requests, capture response values into variables, test JSON payloads and response headers with declarative assertions, and generate JUnit or HTML test reports. This tutorial walks you through installing Hurl on Linux, crafting plain-text request files, asserting API responses, and running automated integration suites.
Installing Hurl on Linux
Hurl is distributed across multiple package repositories and as standalone pre-compiled binaries for x86_64 and ARM64 architectures.
Method 1: Install via Native Package Managers
Depending on your Linux distribution, install Hurl using the standard repository package manager:
Ubuntu and Debian:
curl -fsSL https://hurl.dev/install.sh | sudo bash
Alternatively, download the official .deb package from GitHub Releases and install it using dpkg:
wget https://github.com/Orange-OpenSource/hurl/releases/latest/download/hurl_latest_amd64.deb
sudo dpkg -i hurl_latest_amd64.deb
Arch Linux:
sudo pacman -S hurl
Fedora and Red Hat Enterprise Linux:
sudo dnf install hurl
Method 2: Install via Cargo
If you already have Rust and Cargo configured on your system:
cargo install hurl
Verify that Hurl is correctly installed and accessible in your shell environment:
hurl --version
Creating Your First Hurl Request File
Hurl test suites are saved with the .hurl file extension. The file format is deliberately intuitive, mirroring standard HTTP request semantics.
Create a basic test file named api-test.hurl using your preferred text editor:
# Basic GET request check
GET https://httpbin.org/get
User-Agent: Hurl-Client/1.0
# HTTP Response Assertions
HTTP 200
[Asserts]
header "Content-Type" contains "application/json"
jsonpath "$.headers.User-Agent" == "Hurl-Client/1.0"
duration < 2000
To execute the file and display formatted response output:
hurl api-test.hurl
If all assertions succeed, Hurl exits with return code 0. If an assertion fails, Hurl highlights the exact line, expected value, and actual value with colourful error diagnostics.
Chaining Requests and Capturing Variables
One of Hurl’s most powerful capabilities is chaining requests by capturing data from one response and reusing it in subsequent calls:
# Step 1: Authenticate and retrieve token
POST https://api.example.com/v1/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "secretpassword"
}
HTTP 200
[Captures]
auth_token: jsonpath "$.data.access_token"
user_id: jsonpath "$.data.user.id"
[Asserts]
status == 200
# Step 2: Fetch user profile using the captured token
GET https://api.example.com/v1/users/{{user_id}}/profile
Authorization: Bearer {{auth_token}}
HTTP 200
[Asserts]
header "Content-Type" contains "application/json"
jsonpath "$.status" == "active"
jsonpath "$.account_type" == "enterprise"
Running Hurl in Test Mode and Generating Reports
For Continuous Integration (CI) pipelines or automated server health audits, run Hurl with the --test flag to suppress verbose response bodies and output concise status summaries:
hurl --test api-test.hurl
To test an entire directory of test files and generate an interactive HTML report:
hurl --test --report-html ./reports/ tests/*.hurl
This command executes all .hurl test suites in sequential order, calculates request durations, and exports an HTML dashboard containing drill-down timelines and HTTP payloads into the specified directory.
Essential Hurl Command Options
The table below highlights commonly used command-line flags for tweaking execution behaviour:
| Flag | Description | Typical Use Case |
|---|---|---|
--test |
Enables test mode with concise pass/fail summary output | CI/CD pipelines, Git pre-commit hooks |
--variable key=val |
Injects dynamic runtime variables into template placeholders | Switching between staging and production URLs |
--insecure, -k |
Bypasses SSL certificate verification | Local development and staging servers |
--verbose, -v |
Displays full HTTP headers and network connection details | Debugging failed connection handshakes |
--retry <n> |
Retries failed requests up to specified count | Handling transient network timeouts |