How to Trace An HTTP/HTTPS Request with cURL

Configuring a web server like Apache2 or NGINX can get quite complicated given the number of elements that are now involved in serving networked data.

The cURL command line tool provides excellent options to print out exactly what it’s doing when it requests an object from a remote server.

Simply use the following options when using cURL to print the complete interaction between cURL and the server:

curl -vIL <URL>

Running cURL with these options against https://bash-prompt.net gives the following output:

$ curl -vIL https://bash-prompt.net
* processing: https://bash-prompt.net
*   Trying 5.161.150.90:443...
* Connected to bash-prompt.net (5.161.150.90) port 443
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=bash-prompt.net
*  start date: Jun 29 21:15:21 2023 GMT
*  expire date: Sep 27 21:15:20 2023 GMT
*  subjectAltName: host "bash-prompt.net" matched cert's "bash-prompt.net"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/2
* h2 [:method: HEAD]
* h2 [:scheme: https]
* h2 [:authority: bash-prompt.net]
* h2 [:path: /]
* h2 [user-agent: curl/8.2.1]
* h2 [accept: */*]
* Using Stream ID: 1
> HEAD / HTTP/2
> Host: bash-prompt.net
> User-Agent: curl/8.2.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 103
HTTP/2 103
< link: </css/style.min.b2fbc87dbc5aadff85dc5abfc3a66921a17207eebbb2238c0a1d4db94d7cfab6.css>; rel=preload, </js/bundle.min.580988ed2982bcbb74a1773c7abea97b43e4c43b9324e10cda0813ec6ec4bb67.js>; rel=preload, </css/style.min.b2fbc87dbc5aadff85dc5abfc3a66921a17207eebbb2238c0a1d4db94d7cfab6.css>; rel=preload, </js/bundle.min.580988ed2982bcbb74a1773c7abea97b43e4c43b9324e10cda0813ec6ec4bb67.js>; rel=preload
link: </css/style.min.b2fbc87dbc5aadff85dc5abfc3a66921a17207eebbb2238c0a1d4db94d7cfab6.css>; rel=preload, </js/bundle.min.580988ed2982bcbb74a1773c7abea97b43e4c43b9324e10cda0813ec6ec4bb67.js>; rel=preload, </css/style.min.b2fbc87dbc5aadff85dc5abfc3a66921a17207eebbb2238c0a1d4db94d7cfab6.css>; rel=preload, </js/bundle.min.580988ed2982bcbb74a1773c7abea97b43e4c43b9324e10cda0813ec6ec4bb67.js>; rel=preload

< HTTP/2 200
HTTP/2 200
< last-modified: Mon, 31 Jul 2023 08:03:20 GMT
last-modified: Mon, 31 Jul 2023 08:03:20 GMT
< etag: "e4a-601c3dd1f270a"
etag: "e4a-601c3dd1f270a"
< accept-ranges: bytes
accept-ranges: bytes
< content-length: 3658
content-length: 3658
< cache-control: max-age=172800
cache-control: max-age=172800
< expires: Thu, 10 Aug 2023 06:49:21 GMT
expires: Thu, 10 Aug 2023 06:49:21 GMT
< vary: Accept-Encoding
vary: Accept-Encoding
< content-type: text/html
content-type: text/html
< date: Tue, 08 Aug 2023 06:49:21 GMT
date: Tue, 08 Aug 2023 06:49:21 GMT
< server: Apache/2.4.57 (Debian)
server: Apache/2.4.57 (Debian)

<
* Connection #0 to host bash-prompt.net left intact

This informs us that, amongst a great deal of other useful information, the SSL certificate is good, TLS/1.3 is being used and that HTTP/2 is also employed.

I have found this command a short and very helpful tool to check that the changes I make to, in my case Apache2, are actually being used by connecting clients.