Everyone uses curl, the Swiss army knife of Internet transfers. While this tool has performed transfers and provided and a solid set of command line options for decades, new ones are added over time.
This talk goes through and focuses on some of the most powerful and interesting additions to curl done in recent years. The perhaps lesser known curl tricks that might enrich your command lines, extend your “tool belt” and make you more productive. Also trurl, the recently created companion tool for URL manipulations you maybe did not yet realize you need.
This presentation might just help you curl better.
1 of 53
Download to read offline
More Related Content
mastering the curl command line with Daniel Stenberg
15. Parallel transfers
by default, URLs are transferred serially, one by one
-Z (--parallel)
By default up to 50 simultaneous
Change with --parallel‐max [num]
Works for downloads and uploads
@bagder
server
client
Upload
Download
$ curl -Z -O https://example.com/[1-1000].jpg
16. --no-clobber
does not overwrite destination, adds a number instead
@bagder
$ touch file
$ curl -O --no-clobber https://example.com/file
$ ls -l file.1
-rw-r--r-- 1 user user 1256 Oct 18 13:27 file.1
17. --remove-on-error
do not save leftovers on error
@bagder
$ curl -O --remove-on-error --max-time 2 https://example.com/file
$ curl: (28) Operation timed out after 2000 …
$ ls -l file
ls: cannot access 'file': No such file or directory
18. --skip-existing
avoid the download if the local file is already there
(coming in 8.10.0)
@bagder
$ curl -O --skip-existing https://example.com/file
$
$ curl -O --skip-existing --remove-on-error https://example.com/file
$
19. transfer controls
stop slow transfers
--speed‐limit <speed> --speed‐time <seconds>
transfer rate limiting
curl --limit-rate 100K https://example.com
no more than this number of transfer starts per N time units
curl --rate 2/s https://example.com/[1-20].jpg
curl --rate 3/2h https://example.com/[1-20].html
curl --rate 14/3m https://example.com/day/[1-365]/fun.html
Truly limit the maximum file size accepted:
curl --max-filesize 238M https://example.com/the-biggie -O
@bagder
21. Massaging URL “queries”
Queries are often name=value pairs separated by amperands (&)
name=daniel & tool=curl & age=old
Add query parts to the URL with --url-query [content]
content is (for example) “name=value”
“value” gets URL encoded to keep the URL fine
@bagder
scheme://user:password@host:1234/path?query#fragment
23. config file
“command lines in a file”
one option (plus argument) per line
$HOME/.curlrc is used by default
-K [file] or --config [file]
can be read from stdin
can be generated (and huge)
10MB line length limit
@bagder
24. Variables in a config file
user = “$USER:$SECRET” - cannot could not be done
introducing this syntax risks breaking countless existing files
what if you would rather read that info from a separate file?
@bagder
25. --variable
Sets a curl variable on command line or in a config file
--variable name=content
variable = name=content
There can be an unlimited amount of variables.
A variable can hold up to 10M of content
Variables are set in a left to right order as it parses the command line or config file.
@bagder
26. Setting variables
Content for the variable can be read from a file:
--variable name@file
Content for the variable can be read from stdin:
--variable name@-
Variable content
may be binary
@bagder
27. Environment variables
A variable can be imported from the environment. Error if non-existing:
--variable %name
Import a name from the environment, but if not set use a default value:
--variable %name=default
Import a name from the environment, but if not set read the default value from
a file:
--variable %name@filename
@bagder
28. Expanding variables
Variables can be used in command line option arguments
Must be explicitly asked for
Introducing the --expand- prefix
Reference a variable as {{name}}
A non-existing variable will expand as blank/nothing
Trying to show a variable with a null byte causes error
Examples:
--expand-data “{{content}}”
--expand-url “https://{{host}}/user/{{user}}”
@bagder
Variable content
may be binary
29. Expansion functions
When expanding a variable, functions can be applied
{{name:function}}
Functions alter how the variable is expanded
Multiple functions can be applied in a left-to-right order:
{{name:func1:func2:func3}}
Provided functions:
trim, json, url and b64
@bagder
$ curl --variable %DATA --expand-data ‘{{DATA:trim:b64}}’
https://example.com/
31. wcurl is a command line tool which lets you download URLs without having to
remember any parameters.
Invoke wcurl with a list of URLs you want to download and wcurl picks sane
defaults; using curl under the hood.
$ wcurl https://curl.se/download/curl-8.9.1.tar.xz
@bagder
https://curl.se/wcurl/
33. --write-out
outputs text, information and HTTP headers after a transfer is completed
curl -w "formatted string" http://example.com/
curl -w @filename http://example.com/
curl -w @- http://example.com/
Information from over 50 “variables”
curl -w "Type: %{content_type}nCode: %{response_code}n" …
Show the information as JSON:
curl -w ‘%{json}’ …
Show HTTP response header contents
curl -w "Server: %header{server}nDate: %header{date}n" …
@bagder
37. trace even more
@bagder
--trace-config tells curl what more to include in the trace
“all”, “HTTP/2, “HTTP/3”, “TLS”, …
This was previously only possible in debug builds
$ curl --trace dump --trace-config all https://example.com/one
39. Better option help
Coming in 8.10.0
curl -h [option]
@bagder
$ curl -h --fail-early
--fail-early
Fail and exit on the first detected transfer error.
When curl is used to do multiple transfers on the command line, it
attempts to operate on each given URL, one by one. By default, it
ignores errors if there are more URLs given and the last URL's
success determines the error code curl returns. Early failures are
"hidden" by subsequent successful transfers.
Using this option, curl instead returns an error on the first
transfer that fails, independent of the amount of URLs that are
given on the command line. This way, no transfer failures go
undetected by scripts and similar.
This option does not imply --fail, which causes transfers to fail
due to the server's HTTP status code. You can combine the two
options, however note --fail is not global and is therefore
contained by --next.
This option is global and does not need to be specified for each
use of --next. Providing --fail-early multiple times has no extra
effect. Disable it again with --no-fail-early.
Example:
curl --fail-early https://example.com https://two.example
See also --fail and --fail-with-body.
41. etags
do the transfer only if…
The remote resource is “different”
curl --etag-save remember.txt -O https://example.com/file
curl --etag-compare remember.txt -O https://example.com/file
Both can be used at once for convenient updates:
curl --etag-save remember.txt --etag-compare remember.txt -O
https://example.com/file
Better than time conditions
@bagder
42. HTTP alt-svc
server tells client: there is one or more alternatives at "another place"
The Alt-Svc: response header
Each entry has an expiry time
Only recognized over HTTPS
curl --alt-svc altcache.txt https://example.com/
The alt-svc cache is a text based readable file
@bagder
43. HTTP HSTS
HSTS - HTTP Strict Transport Security
This host name requires HTTPS going forward
The Strict-Transport-Security: response header
Only recognized over HTTPS
Each entry has an expiry time
curl --hsts hsts.txt http://example.com/
The HSTS cache is a text based readable file
@bagder
44. HTTP version 3 changed how data is sent over the wire - again
HTTP/3 is done over QUIC, a new transport protocol
QUIC replaces TCP + TLS, and runs over UDP
curl hides protocol differences from users
HTTP/3 is only for HTTPS, there is no clear text version
with --http3 you can ask curl to attempt HTTP/3
--http3 races HTTP/3 against HTTP/1+2 and picks the winner
With HTTP/3, curl can do multiplexed transfers with -Z
@bagder
45. connection race
curl uses both IPv6 and IPv4 when possible - and races them against each other
“Happy eyeballs”
Restrict to a fixed IP version with --ipv4 or --ipv6
@bagder
curl.se
client
curl.se has address 151.101.129.91
curl.se has address 151.101.193.91
curl.se has address 151.101.1.91
curl.se has address 151.101.65.91
curl.se has IPv6 address 2a04:4e42:800::347
curl.se has IPv6 address 2a04:4e42:a00::347
curl.se has IPv6 address 2a04:4e42:c00::347
curl.se has IPv6 address 2a04:4e42:e00::347
curl.se has IPv6 address 2a04:4e42::347
curl.se has IPv6 address 2a04:4e42:200::347
curl.se has IPv6 address 2a04:4e42:400::347
curl.se has IPv6 address 2a04:4e42:600::347
DNS
2a04:4e42:800::347
2a04:4e42:a00::347
2a04:4e42:c00::347
2a04:4e42:e00::347
2a04:4e42::347
2a04:4e42:200::347
2a04:4e42:400::347
2a04:4e42:600::347
151.101.129.91
151.101.193.91
151.101.1.91
151.101.65.91
IPv6
IPv4
46. @bagder
racing
curl.se
client
curl.se has address 151.101.129.91
curl.se has address 151.101.193.91
curl.se has address 151.101.1.91
curl.se has address 151.101.65.91
curl.se has IPv6 address 2a04:4e42:800::347
curl.se has IPv6 address 2a04:4e42:a00::347
curl.se has IPv6 address 2a04:4e42:c00::347
curl.se has IPv6 address 2a04:4e42:e00::347
curl.se has IPv6 address 2a04:4e42::347
curl.se has IPv6 address 2a04:4e42:200::347
curl.se has IPv6 address 2a04:4e42:400::347
curl.se has IPv6 address 2a04:4e42:600::347
DNS
2a04:4e42:800::347
2a04:4e42:a00::347
2a04:4e42:c00::347
2a04:4e42:e00::347
2a04:4e42::347
2a04:4e42:200::347
2a04:4e42:400::347
2a04:4e42:600::347
151.101.129.91
151.101.193.91
151.101.1.91
151.101.65.91
h2 IPv6
h2 IPv4
h3 IPv4
h3 IPv6
49. Going next?
the Internet does not stop or slow down
protocols and new ways of doing Internet transfers keep popping up
curl will keep expanding, get new features, get taught new things
we, the community, make curl do what we think it should do
you can affect what’s next for curl
@bagder