// DevOps
curl for beginners: your first step into the world of HTTP requests
Published on 2026-09-22
curl — a command-line utility for transferring data via URLs. It sends a request to a server and shows the response: an HTML page, JSON from an API, headers, or a file. The name stands for Client URL. Besides HTTP and HTTPS, curl works with FTP, SFTP, SMTP, IMAP, and other protocols.
curl is available on almost every Linux and macOS system, and is included in Windows 10 and 11. People use it to:
- test APIs and web services without a browser;
- download files in scripts;
- check site availability, redirects, and certificates;
- find where time is lost when loading a page;
- send test emails via SMTP.
First request
Without options curl performs a GET request and prints the response body to the terminal:
curl https://example.comMain flags
Descriptions — from the official curl manual.
| Flag | What it does |
|---|---|
-s, --silent | do not show the progress meter and error messages |
-S, --show-error | together with -s: still show an error message if the request failed |
-L, --location | follow redirects (3xx) |
-I, --head | fetch only response headers (for HTTP — HEAD request) |
-i, --include | print response headers along with the body |
-v, --verbose | verbose output: connection, TLS, request headers (>) and response headers (<) |
-o file | save the response to the specified file |
-O | save the file with the name from the URL |
-X method | set the request method: POST, PUT, DELETE, etc. |
-H "Name: value" | add a header |
-d data | send data with POST, by default as application/x-www-form-urlencoded |
--data-urlencode | same as -d, but URL-encodes the value |
--json data | send JSON: sets Content-Type and Accept: application/json |
-u user:pass | username and password for basic authentication |
-f, --fail | on 400+ response, exit with code 22 and do not output the body |
--retry N | retry the request on transient errors |
-w format | print informational data after the request: response code, timing stages |
-m, --max-time | limit the total operation time in seconds |
--connect-timeout | limit only the time to establish the connection |
-x address | send the request through a proxy |
-k, --insecure | do not verify the server certificate |
The -k flag disables TLS certificate verification, and the connection is no longer protected against tampering. It is acceptable only for diagnostics on your own testbed; it has no place in scripts and production settings.
The combination -sS is convenient in scripts: progress does not clutter the output, but errors are visible. For downloading in a script people usually write curl -fsSL: no progress, error messages shown, follow redirects, and a non-zero exit code if the server responded with an error.
Headers and redirects
View only response headers:
curl -I https://example.comCheck where a redirect chain leads and see the headers of each response:
curl -sIL http://example.comVerbose output with TLS connection details is the first thing to do if a request behaves strangely:
curl -v https://example.com -o /dev/nullAPI requests
GET request with an Authorization header:
curl -s -H "Authorization: Bearer $TOKEN" https://api.example.com/v1/itemsPOST with form data:
curl -d "name=mike&age=30" https://api.example.com/registerIf -d is specified, the POST method is chosen automatically; you don’t need to add -X POST.
POST with JSON:
curl --json '{"name": "mike", "age": 30}' https://api.example.com/usersIn older versions of curl that don’t have --json yet, the same is written like this:
curl -H "Content-Type: application/json" -d '{"name": "mike", "age": 30}' https://api.example.com/usersPUT and DELETE:
curl -X PUT --json '{"age": 31}' https://api.example.com/users/42
curl -X DELETE https://api.example.com/users/42Basic authentication:
curl -u admin:password https://example.com/admin/If you only specify a username (-u admin), curl will ask for a password interactively, and it won’t remain in the command history.
Downloading and uploading files
# save with the name from the URL
curl -O https://example.com/file.zip
# save under your own name
curl -o backup.zip https://example.com/file.zip
# send a file via a form (multipart/form-data)
curl -F "file=@report.pdf" https://example.com/upload
# upload a file via PUT
curl -T report.pdf https://example.com/files/report.pdfHow long a request takes
The -w flag prints informational variables after the request. This way you can understand at which stage time is being lost:
curl -o /dev/null -s -w "DNS: %{time_namelookup}\nTCP: %{time_connect}\nTLS: %{time_appconnect}\nFirst byte: %{time_starttransfer}\nTotal: %{time_total}\nCode: %{http_code}\n" https://example.comAll values are in seconds from the start of the request. If DNS time is high, the problem is with the resolver; if time to first byte is high on a fast connection, the application itself is responding slowly. More on network troubleshooting — see the article “Network troubleshooting: diagnostic utilities”.
Response code alone, for example for monitoring in a script:
curl -s -o /dev/null -w "%{http_code}\n" https://example.comTimeouts, retries, and proxies
# don't wait longer than 5 seconds for the connection, and longer than 20 seconds for the whole request
curl --connect-timeout 5 -m 20 https://example.com
# retry up to three times on transient errors
curl --retry 3 https://example.com
# request via an HTTP proxy or SOCKS5
curl -x http://proxy.example.com:3128 https://example.com
curl -x socks5h://127.0.0.1:1080 https://example.comThe scheme socks5h:// means that the proxy resolves the server name, not your computer.
Mail protocols
Sending an email via SMTP
curl --url "smtp://smtp.example.com:587" \
--ssl-reqd \
--mail-from "sender@example.com" \
--mail-rcpt "recipient@example.com" \
--upload-file email.txt \
--user "username:password"--ssl-reqd— require encryption (STARTTLS);--mail-fromand--mail-rcpt— sender and recipient;--upload-file— a file with the email: headersFrom,To,Subject, a blank line, and the body.
Listing folders via IMAP
curl --url "imaps://imap.example.com" \
--user "username:password" \
-X 'LIST "" "*"'Common mistakes
- Forgotten
-L. The server responds with a redirect, andcurlshows an empty response or a “Moved” page. -kin production scripts. The script stops noticing certificate tampering. It’s better to fix the certificate chain on the server or specify your own root certificate via--cacert.- Passwords and tokens on the command line. They stay in the shell history and are visible in the process list. It’s better to pass tokens via environment variables or a file (
-H @headers.txt). - Missing
-fin scripts. Without it, a 404 or 500 response is considered a successful request, and the script will continue working with a “file” that is actually an error page.
curl nicely complements browser developer tools: its command can be easily saved, repeated, and inserted into a script or a CI job.
How to use curl to find the cause of a problem — send a request to a specific server bypassing DNS, trace the redirect chain, break down where time is lost — is described in the article “Debugging HTTP with curl”. Certificate and TLS checks are covered in “TLS debugging: curl and openssl s_client”.
// Contact
Need help?
Get in touch with me and I'll help solve the problem
I reply within one business day (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related