Network
curl Exit Code Reference
A complete reference for curl command exit codes — meanings, common causes, and fixes for developers debugging CI/CD pipelines and shell scripts. Includes a lookup tool — enter a code number to see details instantly.
| Code | Constant Name | Meaning | Common Causes |
|---|---|---|---|
| Connection / Initialization Errors | |||
| 1 | CURLE_UNSUPPORTED_PROTOCOL | Indicates that curl does not support the protocol specified in the URL. | Occurs when using a curl binary built without that protocol enabled (e.g. gopher, ldap), or a typo in the URL scheme. |
| 2 | CURLE_FAILED_INIT | Indicates that curl's internal initialization failed. | A rare low-level initialization failure, typically caused by insufficient memory or an abnormal environment. |
| 3 | CURLE_URL_MALFORMAT | Indicates that the specified URL is malformed and curl cannot parse it. | Occurs when the URL is missing its scheme (e.g. http://) or contains invalid characters. |
| 5 | CURLE_COULDNT_RESOLVE_PROXY | Indicates that curl failed to resolve the hostname of the specified proxy server. | Caused by a typo in the hostname passed to --proxy, or a DNS failure specific to the proxy. |
| 6 | CURLE_COULDNT_RESOLVE_HOST | Indicates that curl failed to resolve (DNS) the hostname of the destination server. | Typically caused by a typo in the domain name, a DNS server outage, or running in an offline environment. |
| 7 | CURLE_COULDNT_CONNECT | Indicates that the hostname was resolved, but curl failed to establish a TCP connection to the server. | Occurs due to an incorrect port number, a firewall blocking the connection, or the server being down. |
| 8 | CURLE_WEIRD_SERVER_REPLY | Indicates that curl received an unexpected response from the server that it could not interpret. | Common when an FTP server returns a non-standard response, or when curl accidentally connects to a server speaking a different protocol. |
| 9 | CURLE_REMOTE_ACCESS_DENIED | Indicates that curl connected to the server but access was denied. | Occurs due to insufficient permissions for an FTP directory, or when the server enforces an IP restriction. |
| Data Transfer Errors | |||
| 18 | CURLE_PARTIAL_FILE | Indicates that the transfer was interrupted before completion, so only part of the file was received. | Occurs due to a brief network interruption, or when the server closes the connection earlier than the announced Content-Length. |
| 23 | CURLE_WRITE_ERROR | Indicates that curl failed to write data to the local disk or the destination callback. | Occurs when the disk is full, or curl lacks write permission for the output file. |
| 26 | CURLE_READ_ERROR | Indicates that curl failed to read the local file to be uploaded. | Occurs when the file specified with -T/--upload-file does not exist, or curl lacks read permission for it. |
| 52 | CURLE_GOT_NOTHING | Indicates that curl connected to the server but received no response at all. | Typically caused by the server process crashing mid-request, or a misconfiguration that returns an empty response. |
| 55 | CURLE_SEND_ERROR | Indicates that curl failed to send data over the network. | Occurs when the remote side disconnects immediately after the connection is established, or due to a local network interface issue. |
| 56 | CURLE_RECV_ERROR | Indicates that curl failed to receive data from the network. | Commonly seen when the remote side unexpectedly resets the connection mid-transfer (Connection reset by peer). |
| 63 | CURLE_FILESIZE_EXCEEDED | Indicates that the file size exceeded the limit set with --max-filesize. | Occurs when the response turns out larger than expected and hits the safety limit you configured. |
| 78 | CURLE_REMOTE_FILE_NOT_FOUND | Indicates that the specified file does not exist on the remote server (e.g. FTP). | Occurs due to a typo in the FTP path, or when the target file has already been deleted or moved. |
| SSL/TLS Certificate Errors | |||
| 35 | CURLE_SSL_CONNECT_ERROR | Indicates that a problem occurred during the SSL/TLS handshake, preventing the connection from being established. | Commonly caused by a mismatch between the TLS versions or cipher suites supported by the server and the client. |
| 51 | CURLE_PEER_FAILED_VERIFICATION | Indicates that verification of the server certificate failed (e.g. the certificate does not match the hostname). | Occurs when accessing a self-signed certificate, or when the certificate's Common Name/SAN differs from the destination hostname. |
| 58 | CURLE_SSL_CERTPROBLEM | Indicates a problem with the locally specified client certificate. | Typically caused by an invalid format in the certificate file passed with --cert, or an incorrect passphrase. |
| 60 | CURLE_SSL_CACERT | Indicates that curl could not verify the CA certificate chain used to validate the server certificate. | Occurs when the CA certificate bundle is outdated, or a self-signed CA (such as a corporate proxy's) is not registered in the trust store. -k/--insecure is a workaround, but it is not recommended for production use. |
| HTTP / Authentication Errors | |||
| 22 | CURLE_HTTP_RETURNED_ERROR | Indicates that, with the -f/--fail option specified, the HTTP response returned an error status of 400 or higher. | Triggered intentionally in CI/CD scripts that use curl -f so that an API error status is detected as a failure. |
| 67 | CURLE_LOGIN_DENIED | Indicates that the login (authentication) to the server was rejected. | Typically caused by an incorrect username or password, or an account lockout on protocols such as FTP/SMTP. |
| Other | |||
| 27 | CURLE_OUT_OF_MEMORY | Indicates that curl failed to allocate memory during execution. | A rare situation, such as attempting to handle a huge file on a memory-constrained system. |
| 28 | CURLE_OPERATION_TIMEDOUT | Indicates that the operation did not complete within the time limit set with --connect-timeout/--max-time, etc. | One of the most frequent errors seen in CI, caused by a slow server response, network latency, or a timeout value set too short. |
| 47 | CURLE_TOO_MANY_REDIRECTS | Indicates that the number of redirects exceeded the limit set with --max-redirs. | Occurs with a redirect loop (301/302 redirecting circularly), or a legitimate redirect chain longer than the default limit (50). |
Tips
- You can check the exit code immediately with
$?(Bash) or%errorlevel%(Windows). In shell scripts, branching likecurl ... || echo "failed with $?"is a handy pattern. - 28 (timeout) and 7 (connection failed) are often confused, but 28 occurs when the response is slow after a connection is made, while 7 occurs when the TCP connection itself could never be established.
- If you get 60 (CA certificate error), don't just work around it with
-k/--insecure— first check whether your CA certificate bundle (ca-certificates) is up to date. Using -k routinely in production increases the risk of man-in-the-middle attacks. - 22 (HTTP error) only occurs when you add the
-f/--failoption. Without it, curl returns exit code 0 (success) even for a 404 or 500 response, so always add -f if you want CI to detect failures.
FAQ
echo $? in Bash/Zsh, echo %errorlevel% in the Windows Command Prompt, or $LASTEXITCODE in PowerShell.--connect-timeout and --max-time settings and extend them if needed. If the server is consistently slow to respond, also check server load and the network path (proxies, VPNs, etc.).curl -f (--fail) option so that curl returns exit code 22 whenever the HTTP response is 400 or higher. Without it, successfully fetching an error page still results in exit code 0.
Side Note — The curl Exit Code System
curl is a command-line tool whose development began in 1996 by Daniel Stenberg, originally under the name "httpget." Today curl ships by default on virtually every Linux distribution, macOS, and Windows 10 and later, making it one of the most fundamental tools for web developers.
The exit code system maps directly onto libcurl's internal error enum, CURLcode, and is defined as a sequential numbering starting with `CURLE_OK` (success, exit code 0). Gaps in the numbering exist because some error codes were deprecated or merged during development.
Interestingly, curl's exit codes form their own independent system, separate from the general POSIX convention (0 = success, 1 = general error). This means that when handling exit codes across multiple tools in a shell script, you need to check each tool's manual individually to understand its meaning.