When you encounter the message "ALPN, server did not agree to a protocol" in curl requests, it indicates a mismatch between the Application-Layer Protocol Negotiation (ALPN) extensions supported by your client and the server. This typically occurs during the TLS handshake process.
This error frequently appears when:
- Making HTTPS requests to servers that don't support HTTP/2
- Using older versions of curl against modern servers
- Having protocol mismatches in development environments
To better understand what's happening, add verbose output to your curl command:
curl -v --http1.1 https://example.com/api
The output will show the ALPN negotiation process and which protocols were offered/selected.
Here are several ways to resolve this:
1. Force HTTP/1.1
curl --http1.1 https://example.com
2. Check and Upgrade curl Version
curl --version
If you're using version below 7.47.0, consider upgrading as it has better ALPN support.
3. Explicitly Set ALPN Protocols
curl --alpn-protos "http/1.1" https://example.com
Here's how you might implement this in a script with proper error handling:
#!/bin/bash response=$(curl -sS --http1.1 --fail https://api.example.com/data 2>&1) if [ $? -ne 0 ]; then echo "Request failed:" echo "$response" exit 1 fi echo "Success:" echo "$response" | jq .
While this message appears as a warning, it's typically not the cause of 400 errors. The 400 Bad Request usually indicates malformed syntax in your request. To confirm, check:
- Request headers and body format
- Authentication tokens
- Endpoint URL accuracy
For developers working with multiple protocols, you can test different combinations:
# Test HTTP/2 explicitly curl --http2 https://example.com # Compare with HTTP/1.1 curl --http1.1 https://example.com # See supported protocols openssl s_client -connect example.com:443 -alpn "h2,http/1.1"
When making HTTPS requests using cURL, you might encounter the warning: ALPN, server did not agree to a protocol
. This occurs during the TLS handshake when the client and server can't negotiate an application-layer protocol through ALPN (Application-Layer Protocol Negotiation).
Interestingly, this message is often just a warning rather than an error. Many servers operate perfectly fine without ALPN negotiation. However, in some cases - particularly with HTTP/2 servers - it can lead to connection failures or fallback to less optimal protocols.
To better understand what's happening, use cURL's verbose mode:
curl -v https://example.com
Look for lines containing ALPN
in the output. You might see something like:
* ALPN, offering h2
* ALPN, offering http/1.1
* ALPN, server did not agree to a protocol
If you specifically need HTTP/2, you can force the protocol:
curl --http2 https://example.com
Or for HTTP/1.1:
curl --http1.1 https://example.com
If you control the server, ensure your TLS configuration supports ALPN. For example, in Nginx:
listen 443 ssl http2;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
The ALPN warning becomes critical when:
- You require HTTP/2 features
- You're implementing protocol-specific functionality
- The server strictly requires ALPN negotiation
Try these cURL commands to test various protocol scenarios:
# Test HTTP/2 explicitly
curl --http2 -I https://example.com
# Test with ALPN disabled (not recommended for production)
curl --no-alpn -I https://example.com
# Check supported protocols
openssl s_client -alpn h2 -connect example.com:443
Don't confuse ALPN with:
- NPN (Next Protocol Negotiation) - the older, deprecated version
- SNI (Server Name Indication) - which handles virtual hosting
- The TLS protocol version itself
While the ALPN warning might appear alongside HTTP 400 errors, they're usually unrelated. A 400 Bad Request typically indicates:
- Malformed request headers
- Invalid request syntax
- Missing required parameters
To debug 400 errors, examine your request headers and body carefully.
In most cases, the ALPN warning is harmless. But if you're developing protocol-sensitive applications or troubleshooting connection issues, understanding ALPN negotiation becomes crucial. The key is to determine whether it's actually affecting your application's functionality or just appearing as background noise in your logs.