How to Use curl in PowerShell: curl.exe vs. the Alias

To use curl in PowerShell, type curl.exe instead of curl. Windows 10 and 11 include the real curl, and the .exe makes sure you get it rather than an alias:

curl.exe -s -o NUL -w "Status: %{http_code}`n" https://example.com

Output:

Status: 200

In Windows PowerShell 5.1, plain curl is an alias for Invoke-WebRequest, so your curl options fail. Below I show the difference, send JSON without losing quotes and translate curl flags to PowerShell cmdlets.

curl vs. curl.exe in PowerShell

What curl runs depends on your PowerShell version. This checks it:

$cmd = Get-Command -Name curl | Select-Object -First 1
if ($cmd.CommandType -eq 'Alias') { "curl is an alias for $($cmd.Definition)" }
else { "curl is the program $($cmd.Source)" }

Output:

curl is the program C:\WINDOWS\system32\curl.exe
Windows PowerShell curl alias for Invoke-WebRequest
In Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest

PowerShell 7 removed the alias, so curl runs curl.exe from System32. Typing curl.exe works the same in both, which is why I use it in scripts. curl.exe has shipped with Windows since Windows 10 version 1803.

For downloads without curl, see downloading a file from a URL.

Get JSON with curl.exe or Invoke-RestMethod

curl.exe returns text, so pipe it to ConvertFrom-Json. Invoke-RestMethod turns JSON into objects by itself:

$url = 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest'

$fromCurl = curl.exe -s $url | ConvertFrom-Json
$fromIrm = Invoke-RestMethod -Uri $url
"curl.exe:          $($fromCurl.tag_name)"
"Invoke-RestMethod: $($fromIrm.tag_name)"

Output:

curl.exe:          v7.6.6
Invoke-RestMethod: v7.6.6

Both get the same release tag. I reach for Invoke-RestMethod when I’m working with the data in PowerShell.

POST JSON with curl.exe without losing quotes

Here’s the most common curl problem in PowerShell. The same POST works in PowerShell 7:

$json = '{"city":"Austin","orders":42}'
$reply = curl.exe -s -X POST https://httpbin.org/post -H "Content-Type: application/json" -d $json |
    ConvertFrom-Json
"Server received: $($reply.data)"

Output:

Server received: {"city":"Austin","orders":42}
PowerShell 7 curl.exe POST JSON
PowerShell 7 passes the JSON to curl.exe intact

Windows PowerShell 5.1 strips the double quotes from arguments passed to native programs, so the server gets broken JSON:

Server received: {city:Austin,orders:42}
Windows PowerShell 5.1 curl.exe JSON quotes stripped
Same script in Windows PowerShell 5.1: the quotes are gone

PowerShell 7.3 fixed this.

Send the body from a file

A file avoids quoting problems in every version. curl.exe reads it when the value starts with @:

$reply = curl.exe -s -X POST https://httpbin.org/post -H "Content-Type: application/json" -d "@C:\psfaqs\Curl\order.json" |
    ConvertFrom-Json
"Server received: $($reply.data)"

Output:

Server received: {"city":"Austin","orders":42}

Put quotes around the @ value, because PowerShell treats a bare @ as splatting.

curl options and their PowerShell equivalents

curlInvoke-RestMethod / Invoke-WebRequest
-X POST-Method Post
-H “Name: value”-Headers @{ Name = ‘value’ }
-d ‘…’-Body ‘…’
-o file.zip-OutFile file.zip
-u user-Credential (Get-Credential)
-LFollows redirects by default
-k-SkipCertificateCheck (PowerShell 7 only)

The same POST as a cmdlet looks like this:

Invoke-RestMethod -Uri https://httpbin.org/post -Method Post `
    -ContentType 'application/json' -Body '{"city":"Austin","orders":42}'