What is the difference between --head and --request HEAD in Curl?
When working with HTTP requests in cURL, developers often need to retrieve only the headers of a response without downloading the entire body content. This is particularly useful for checking response codes, content types, server information, or file metadata without the overhead of downloading large files. cURL provides two seemingly similar options: --head
and --request HEAD
. While both can be used to make HEAD requests, they have important differences that can affect your request behavior and results.
Understanding HTTP HEAD Requests
Before diving into the differences, it's important to understand what HTTP HEAD requests are designed for. A HEAD request is identical to a GET request except that the server must not return a message body in the response. The server should return the same headers that would be returned for a GET request, making HEAD requests perfect for:
- Checking if a resource exists
- Retrieving metadata about a resource
- Validating cache entries
- Testing server availability
- Getting file size information without downloading the file
The --head Option
The --head
option (short form: -I
) is cURL's dedicated flag for making HEAD requests. When you use this option, cURL automatically:
- Changes the HTTP method to HEAD
- Stops after receiving the headers
- Ignores any response body
- Follows the HTTP specification for HEAD requests
Basic Usage
curl --head https://example.com
# or the short form
curl -I https://example.com
This command will output something like:
HTTP/2 200
date: Fri, 19 Jul 2024 10:30:45 GMT
server: nginx/1.18.0
content-type: text/html; charset=UTF-8
content-length: 1256
last-modified: Thu, 18 Jul 2024 14:22:33 GMT
etag: "64b2f8a9-4e8"
accept-ranges: bytes
Advanced --head Examples
# Check multiple URLs for their status
curl -I https://api.example.com/users/1
curl -I https://api.example.com/users/2
# Follow redirects while making HEAD requests
curl -I -L https://short.url/abc123
# Add custom headers to HEAD request
curl -I -H "Authorization: Bearer token123" https://api.example.com/protected
# Check file size without downloading
curl -I https://example.com/largefile.zip | grep -i content-length
The --request HEAD Option
The --request HEAD
option (short form: -X HEAD
) is part of cURL's general request method specification. This option explicitly sets the HTTP method to HEAD but doesn't automatically configure other HEAD-specific behaviors.
Basic Usage
curl --request HEAD https://example.com
# or the short form
curl -X HEAD https://example.com
Key Differences from --head
While --request HEAD
sets the HTTP method to HEAD, it doesn't automatically:
- Stop processing after headers (though it typically will due to HTTP specification)
- Configure optimal HEAD request handling
- Provide the same level of HEAD-specific optimizations
Practical Differences and Use Cases
When to Use --head
The --head
option is generally preferred for standard HEAD requests because:
# Recommended: Using --head for simple HEAD requests
curl -I https://httpbin.org/status/200
# Check if a file exists and get its metadata
curl -I https://example.com/documents/report.pdf
# Verify API endpoint availability
curl -I https://api.service.com/health
When to Use --request HEAD
The --request HEAD
option is useful when you need more control or are combining it with other options:
# When combining with other request options
curl -X HEAD --data "param=value" https://api.example.com/endpoint
# When building complex request chains
curl -X HEAD -H "Content-Type: application/json" https://api.example.com
# When you need explicit method specification for clarity
curl --request HEAD --include https://example.com
Combining with Other cURL Options
Following Redirects
Both options work with redirect following, but --head
is more straightforward:
# Follow redirects with HEAD requests
curl -I -L https://bit.ly/shortened-url
# Equivalent with --request HEAD
curl -X HEAD -L https://bit.ly/shortened-url
Including Response Headers in Output
# Show only headers (default behavior with -I)
curl -I https://example.com
# Show headers and any body content (though HEAD shouldn't return body)
curl -X HEAD --include https://example.com
Authentication and Custom Headers
Both options work seamlessly with authentication:
# Basic authentication with HEAD request
curl -I -u username:password https://secure.example.com
# API key authentication
curl -I -H "X-API-Key: your-api-key" https://api.example.com/data
# OAuth token with custom request
curl -X HEAD -H "Authorization: Bearer your-token" https://api.example.com/protected
Performance Considerations
Network Efficiency
HEAD requests are inherently more efficient than GET requests for metadata retrieval:
# Efficient: Only retrieve headers (typical size: 500-2000 bytes)
curl -I https://example.com/large-video.mp4
# Inefficient: Download entire file to check metadata
curl https://example.com/large-video.mp4 | head -1
Batch Operations
When checking multiple resources, HEAD requests can significantly reduce bandwidth:
#!/bin/bash
# Check status of multiple API endpoints efficiently
endpoints=(
"https://api.service.com/users"
"https://api.service.com/orders"
"https://api.service.com/products"
)
for endpoint in "${endpoints[@]}"; do
echo "Checking $endpoint:"
curl -I "$endpoint" 2>/dev/null | head -1
echo
done
Error Handling and Debugging
Status Code Checking
# Extract just the status code
status=$(curl -I -s https://example.com 2>/dev/null | head -1 | cut -d' ' -f2)
echo "Status: $status"
# Check if resource exists
if curl -I --fail -s https://example.com >/dev/null 2>&1; then
echo "Resource exists"
else
echo "Resource not found or error occurred"
fi
Verbose Output for Debugging
# See detailed request/response information
curl -I -v https://example.com
# Save headers to file for analysis
curl -I https://example.com > headers.txt
Integration with Web Scraping Workflows
When building web scraping applications, HEAD requests are valuable for preliminary checks before committing to full downloads. While tools like Puppeteer handle browser-based interactions, cURL's HEAD requests excel at quick HTTP-level validations.
For API-based scraping workflows, you might combine HEAD requests with subsequent data retrieval:
# First, check if the API endpoint is available
if curl -I --fail -s https://api.example.com/data >/dev/null 2>&1; then
# Then proceed with actual data retrieval
curl -H "Accept: application/json" https://api.example.com/data
else
echo "API endpoint unavailable"
exit 1
fi
Advanced Scenarios and Edge Cases
Handling Non-Standard Servers
Some servers may not properly implement HEAD requests. In such cases, understanding the differences becomes crucial:
# Standard HEAD request (preferred)
curl -I https://well-behaved-server.com/api
# If server has issues with -I, try explicit method
curl -X HEAD https://problematic-server.com/api
# For debugging server behavior
curl -X HEAD -v https://server.com/api 2>&1 | grep -E "(< |> )"
Testing API Endpoints
When developing APIs, HEAD requests help verify endpoint behavior:
# Test if API endpoint supports HEAD method
curl -I https://api.example.com/v1/users
# Verify CORS headers are present
curl -I -H "Origin: https://frontend.com" https://api.example.com/v1/data
# Check rate limiting headers
curl -I -H "X-API-Key: test-key" https://api.example.com/v1/limited-endpoint
Content Validation Workflows
HEAD requests are perfect for content validation in CI/CD pipelines:
#!/bin/bash
# Validate deployed content without downloading
validate_deployment() {
local base_url="$1"
local endpoints=("/" "/api/health" "/static/app.js" "/static/app.css")
for endpoint in "${endpoints[@]}"; do
echo "Checking ${base_url}${endpoint}..."
if curl -I --fail -s "${base_url}${endpoint}" >/dev/null 2>&1; then
echo "✓ ${endpoint} is accessible"
else
echo "✗ ${endpoint} failed"
return 1
fi
done
return 0
}
validate_deployment "https://myapp.com"
Best Practices and Recommendations
Choose --head for Standard Cases
For most HEAD request scenarios, use the --head
or -I
option:
# Preferred for standard HEAD requests
curl -I https://example.com
# Good for checking redirects
curl -I -L https://shortened-url.com
# Optimal for file metadata checks
curl -I https://cdn.example.com/assets/large-file.zip
Use --request HEAD for Complex Scenarios
Reserve --request HEAD
for cases requiring explicit method specification or complex option combinations:
# When you need explicit control over request building
curl -X HEAD --max-time 5 --retry 3 https://unreliable-service.com
# When combining with data for unusual server requirements
curl -X HEAD --data "@query.json" -H "Content-Type: application/json" https://api.example.com
# When scripting requires explicit method clarity
curl --request HEAD --silent --show-error https://example.com
Error Handling Best Practices
Always implement proper error handling when using HEAD requests:
# Robust error handling with detailed feedback
check_resource() {
local url="$1"
local response
if response=$(curl -I -s --fail "$url" 2>/dev/null); then
local status=$(echo "$response" | head -1 | cut -d' ' -f2)
local content_type=$(echo "$response" | grep -i "content-type:" | cut -d' ' -f2-)
echo "✓ $url - Status: $status, Type: $content_type"
return 0
else
local exit_code=$?
echo "✗ $url - Failed (exit code: $exit_code)"
return $exit_code
fi
}
# Usage
check_resource "https://example.com/api/endpoint"
Performance Optimization
When making multiple HEAD requests, consider parallel execution:
# Parallel HEAD requests for faster batch checking
urls=(
"https://api.service1.com/health"
"https://api.service2.com/health"
"https://api.service3.com/health"
)
for url in "${urls[@]}"; do
{
if curl -I --fail -s --max-time 10 "$url" >/dev/null 2>&1; then
echo "$url: UP"
else
echo "$url: DOWN"
fi
} &
done
wait # Wait for all background processes to complete
Troubleshooting Common Issues
Server Doesn't Support HEAD
Some servers may return errors for HEAD requests:
# If HEAD fails, fall back to GET with range header
check_with_fallback() {
local url="$1"
if curl -I --fail -s "$url" >/dev/null 2>&1; then
echo "HEAD supported"
curl -I "$url"
else
echo "HEAD not supported, using GET with range"
curl -s -r 0-0 "$url" | head -1
fi
}
Redirect Handling
When dealing with redirects, understand the behavior differences:
# HEAD with redirects - both options work similarly
curl -I -L https://short.url/redirect
# But explicit method gives more control
curl -X HEAD -L --max-redirs 5 https://multiple.redirects.com
Conclusion
While both --head
and --request HEAD
can achieve similar results for HTTP HEAD requests, --head
(or -I
) is generally the better choice for standard HEAD operations due to its optimized behavior and cleaner syntax. Use --request HEAD
when you need explicit control over the request method or when combining with complex option sets.
The key takeaways are:
- Use
--head
(-I
) for standard HEAD requests - it's optimized and follows HTTP specifications perfectly - Use
--request HEAD
(-X HEAD
) when you need explicit method control or complex option combinations - HEAD requests are essential for efficient metadata retrieval, server health checks, and content validation
- Always implement error handling when working with HEAD requests in scripts
- Consider parallel execution for batch operations to improve performance
Understanding these differences helps you write more efficient and reliable scripts for web scraping, API testing, and HTTP debugging tasks. Whether you're monitoring network requests in automated browser sessions or performing quick HTTP validations, choosing the right HEAD request option ensures optimal performance and predictable behavior in your applications.