A lightweight, profile-based HTTP client that allows you to talk to web servers with minimal effort. Think of it as curl with persistent profile and simplified syntax.
- Features
- Installation
- Configuration
- Quick Start
- Usage
- Examples
- Troubleshooting
- Why httpc and not curl?
- License
Profile-based simplicity - Transform complex curl commands into simple, memorable requests. Store connection details, authentication, and headers in ~/.httpc/profile once, then use clean relative URLs like httpc -p prod GET /api/users instead of repeating lengthy curl parameters every time.
Plus all the HTTP client features you expect:
- Multiple HTTP methods - Support GET, POST, PUT, DELETE, HEAD, etc.
- Authentication support - Basic auth, custom headers
- SSL/TLS support - Custom CA certificates, insecure mode option
- Proxy support - HTTP proxy configuration
- Standard input support - Read request body from stdin
- Multiple compression - gzip, deflate, zstd
- Flexible URL handling - Absolute or relative URLs with profile base
- Verbose mode - Detailed request/response information
Download the appropriate binary from releases for your platform:
macOS (Homebrew):
# Install via Homebrew (easiest method for macOS)
brew install samwisely75/tap/httpcLinux/macOS (Manual):
# Download and extract
curl -L https://github.com/samwisely75/httpc/releases/latest/download/httpc-linux-x64.tar.gz | tar -xz
sudo mv httpc /usr/local/bin/
# Or for macOS
curl -L https://github.com/samwisely75/httpc/releases/latest/download/httpc-macos-x64.tar.gz | tar -xz
sudo mv httpc /usr/local/bin/From crates.io (requires Rust):
cargo install httpcBuild from source:
git clone https://github.com/samwisely75/httpc.git
cd httpc
cargo build --release
sudo cp target/release/httpc /usr/local/bin/Test the installation: httpc --help
No additional dependencies required - httpc is a single, self-contained binary.
httpc looks for configuration in ~/.httpc/profile.
The configuration file uses INI format with multiple profiles. Each profile contains connection details and default headers.
[default]
host = https://api.example.com
user = your-username
password = your-password
insecure = false
ca_cert = /path/to/ca.pem
@content-type = application/json
@user-agent = httpc/0.1
@accept = application/json
@accept-encoding = gzip, deflate
[staging]
host = https://staging-api.example.com
user = staging-user
password = staging-pass
@content-type = application/json
[local]
host = http://localhost:8080
user = admin
password = adminhost- Base URL for requests (required for relative URLs)user- Username for basic authenticationpassword- Password for basic authenticationca_cert- Path to CA certificate file for SSL/TLSinsecure- Skip SSL/TLS certificate verification (true/false)
Any key starting with @ becomes an HTTP header. Please feel free to add any custom headers you need.
Examples:
@content-type→Content-Typeheader@authorization→Authorizationheader@user-agent→User-Agentheader@accept→Acceptheader
# Use default profile
httpc GET /api/endpoint
# Use specific profile
httpc -p staging GET /api/endpoint
httpc --profile production GET /api/endpointCommand line options override profile settings:
# Override user from profile
httpc -p staging --user different-user GET /api/data
# Override host entirely
httpc GET https://completely-different-host.com/api-
Create a profile for your favorite API:
# Create ~/.httpc directory and profile file mkdir -p ~/.httpc echo "[swapi] host = https://swapi.dev/api @content-type = application/json" > ~/.httpc/profile
-
Use the profile to explore the Star Wars universe:
# Now you can use short URLs to explore the galaxy! httpc -p swapi GET /people/1/ # Luke Skywalker httpc -p swapi GET /people/4/ # Darth Vader httpc -p swapi GET /starships/10/ # Millennium Falcon httpc -p swapi GET /films/1/ # A New Hope
-
Or override with full URLs when needed:
# You can always use absolute URLs to override the profile httpc GET https://httpbin.org/get httpc GET https://swapi.dev/api/planets/
The simplest usage is to make a request to any URL:
# GET request
httpc GET https://httpbin.org/get
# POST request with JSON data
httpc POST https://httpbin.org/post '{
"name": "John Doe",
"email": "[email protected]"
}'
# PUT request
httpc PUT https://httpbin.org/put '{"status": "updated"}'
# DELETE request
httpc DELETE https://httpbin.org/deleteYou can pass request body via standard input:
# From file
cat data.json | httpc POST https://api.example.com/users
# From command output
echo '{"query": {"match_all": {}}}' | httpc POST https://elasticsearch.example.com/my-index/_search
# Complex pipeline example
echo '{
"query": {
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
}
}' | httpc GET my-index/_search | jq '.hits.hits[]._source.name'Use profile to avoid repeating connection details:
# Use default profile
httpc GET /api/users
# Use specific profile
httpc -p staging GET /api/users
httpc -p production GET /health# Basic authentication
httpc GET https://api.example.com/protected \
--user admin \
--password secret
# Custom headers
httpc POST https://api.example.com/data \
-H "Authorization: Bearer your-token" \
-H "X-Custom-Header: value" \
'{"data": "value"}'
# SSL options
httpc GET https://self-signed.example.com/api \
--ca-cert /path/to/ca.pem \
--insecure# Through proxy
httpc GET https://api.example.com/data \
--proxy http://proxy.company.com:8080
# Verbose mode for debugging
httpc -v GET https://api.example.com/debug
# Override profile settings
httpc -p production GET /api/data \
--user different-user \
--password different-passWhen using special characters in URLs or query parameters, you may need to escape them or use quotes:
# Query parameters with special characters - escape or quote
httpc GET "/api/search?q=hello world&sort=date"
httpc GET /api/search\?q=hello\ world\&sort=date
# Complex URLs with fragments
httpc GET "https://api.example.com/items?filter=status:active&limit=10#results"
# JSON with special characters in URLs
httpc POST "/api/items?category=tools&type=screws" '{
"name": "Phillips head screw",
"size": "M4"
}'Tip: When in doubt, wrap URLs in double quotes to avoid shell interpretation issues.
For all available options, run:
httpc --help# Test REST API endpoints
httpc GET https://jsonplaceholder.typicode.com/posts/1
httpc POST https://jsonplaceholder.typicode.com/posts '{
"title": "My Post",
"body": "Post content",
"userId": 1
}'# JSON API
httpc POST https://api.example.com/users \
-H "Content-Type: application/json" \
'{"name": "John", "email": "[email protected]"}'
# Form data
httpc POST https://api.example.com/form \
-H "Content-Type: application/x-www-form-urlencoded" \
'name=John&[email protected]'
# File upload simulation
cat document.json | httpc PUT https://api.example.com/documents/123# Check cluster health
httpc -p elastic GET /_cluster/health
# Search documents
echo '{
"query": {
"match": {"title": "search term"}
}
}' | httpc -p elastic GET /my-index/_search
# Index a document
httpc -p elastic PUT /my-index/_doc/1 '{
"title": "My Document",
"content": "Document content here"
}'# Set up profile for different environments
mkdir -p ~/.httpc
cat > ~/.httpc/profile << EOF
[dev]
host = http://localhost:3000
@content-type = application/json
[staging]
host = https://staging-api.company.com
user = api-user
password = staging-password
@authorization = Bearer staging-token
[prod]
host = https://api.company.com
user = api-user
password = production-password
@authorization = Bearer production-token
EOF
# Test the same endpoint across environments
httpc -p dev GET /api/health
httpc -p staging GET /api/health
httpc -p prod GET /api/healthQ: httpc: command not found
A: Make sure httpc is in your PATH. Try which httpc or reinstall following the installation instructions.
Q: SSL certificate errors
A: Use --insecure to skip certificate validation, or provide a CA certificate with --ca-cert /path/to/ca.pem.
Q: Profile not found
A: Check that ~/.httpc/profile exists and contains the profile. Use httpc -p nonexistent GET / to see the error.
Q: Authentication failures
A: Verify credentials in your profile or override with --user and --password flags.
Q: Request body from stdin not working
A: Make sure you're piping data correctly: echo '{"key": "value"}' | httpc POST /api/endpoint
Use verbose mode to see detailed request/response information:
httpc -v GET https://httpbin.org/getThis shows:
- Full request URL and headers
- Response status and headers
- Timing information
- SSL/TLS details
Check your configuration file:
# View current configuration
cat ~/.httpc/profile
# Test with a simple request
httpc -p your-profile GET /simple/endpointI work with Elasticsearch clusters day in and day out. Kibana Dev Tools is ideal, but often unavailable in client environments where I need to SSH into nodes, check logs, and run diagnostic queries from the terminal.
curl works, but it becomes tedious with repetitive parameters:
curl -XGET -u elastic:password -H "content-type: application/json" \
https://elastic-prod.es.us-central1.gcp.cloud.es.io/_cat/indices?vIn Kibana Dev Tools, this is simply:
GET /_cat/indices?vI wanted that same simplicity in the terminal by bringing a profile system into it for easily switching between multiple clusters like aws-cli.
Python and Bash scripts work but become unwieldy and hard to maintain. Sometimes I even need to work with Python 2.6/2.7 that complicate the codes due to the compatibility issues. Rust works perfectly as:
- Single binary - No runtime dependencies, easy deployment
- Performance - Native speed, as fast as curl
- Cross-platform - Works on Linux and macOS
- Reliability - Memory safety and robust error handling
- No compatibility hell - Unlike Python scripts with version dependencies
-
Prerequisites
# Install Rust toolchain curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source ~/.cargo/env
-
Build from source
git clone https://github.com/samwisely75/httpc.git cd httpc cargo build
For contributors working on the codebase, we've set up automated tooling to maintain code quality:
# Automatically fix formatting and linting issues
make fix
# Or manually run individual steps:
cargo fmt # Format code
cargo clippy --fix --allow-dirty # Fix clippy warnings
cargo test # Run testsThe make fix command will:
- ✨ Format all code with
rustfmt - 🔧 Automatically fix clippy warnings (like
uninlined_format_args) - ✅ Verify all lints pass
- 🧪 Run the test suite to ensure nothing broke
Pro tip: Run make fix before committing to ensure your code passes CI!
make help # Show all available targets
make build # Build the project
make test # Run tests
make lint # Check linting only
make fmt # Format code only
make check # Run format + lint + testLicensed under the Elastic License 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at:
https://www.elastic.co/licensing/elastic-license
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.