This article explains how to use the cURL utility in the Windows environment.
What is cURL and What Does It Do?
cURL (Client URL) is a classic *nix command line tool for working with URL requests. It allows sending HTTP and HTTPS requests, download or send a file to the server, access the API, authenticate to a web service, etc.
Why Windows Users Often Confuse cURL with Invoke-WebRequest
It is common for Windows users to confuse the cURL command with the Invoke-WebRequest cmdlet. The problem is that in Windows PowerShell 5.1, the command curl was an alias for Invoke-WebRequest, which often caused confusion with the real cURL utility (curl.exe). Later this alias was removed (since PowerShell 6+), and curl can resolve to the native curl.exe binary depending on PATH resolution.

How cURL Works in PowerShell on Windows
In PowerShell 6+ and 7+, the curl command typically resolves to curl.exe if it is available in the system PATH (commonly located in C:\Windows\System32\curl.exe). The actual executable used depends on command resolution order, not PowerShell itself. Starting with Windows 10 1803 and Windows Server 2019, the curl.exe command is available by default (for earlier versions of Windows, you can manually download cURL from the following link)
Hint. To remove the curl alias, run the following commands:
For temporary fix (only for current session), run the command:
Remove-Item Alias:curl -ErrorAction SilentlyContinueFor permanent fix (add to PowerShell profile), run the command:
if (!(Test-Path $PROFILE)) {
New-Item -ItemType File -Path $PROFILE -Force
}
Add-Content $PROFILE "`nRemove-Item Alias:curl -ErrorAction SilentlyContinue"
Installing and Checking cURL Version on Windows
Verify if the cURL is installed and check its version:
curl -V

The syntax of the Invoke-WebRequest cmdlet and the cURL.exe utility are very different. If you’re accustomed to using the cURL command in a Linux environment, you might find it challenging to translate your familiar commands into PowerShell syntax.
Important note. PowerShell may resolve curl differently depending on environment:
- In PowerShell 5.1 โ alias to Invoke-WebRequest
- In PowerShell 7+ โ native curl.exe
- On Windows โ typically located in C:\Windows\System32\curl.exe
For reliable scripts, you should always use:
curl.exe
Note. Detailed guide on how to use the Invoke-WebRequest cmdlet in Windows.
Common cURL Commands and Their PowerShell Equivalents
Let’s take a look at some examples of typical cURL commands and their equivalents in PowerShell.
Get Raw HTML Content of a Web Page
Get the raw HTML content of a web page and the HTTP response status:
curl https://theitbros.com
PowerShell:
(Invoke-WebRequest -Uri "https://theitbros.com").Content
Retrieve Page Headers Only
Get page status and header only:
curl -I https://theitbros.com PS: Invoke-WebRequest -Uri "https://theitbros.com" -Method Head

Use a Custom User-Agent String
Access a web page using a specific User-Agent:
curl -A "Mozilla/5.0" https://theitbros.com
PS: $response = Invoke-WebRequest -Uri "https://theitbros.com" -UserAgent "Mozilla/5.0"
Download Files or Pages
Download the entire web page:
curl -o C:\PS\theitbros_home.html https://theitbros.com PS: Invoke-WebRequest -Uri "https://theitbros.com" -OutFile "C:\PS\theitbros_home2.html"

Get File Size (Content-Length)
Get the file size (the size in bytes specified in the Content-Length field):
curl -IL https://download.sysinternals.com/files/PSTools.zip PS: $response = Invoke-WebRequest -Uri "https://download.sysinternals.com/files/PSTools.zip" -Method Head $response.Headers["Content-Length"]

Download a file (file will be saved in the current directory: pwd):
curl -O https://theitbros.com/test.zip
PS: Invoke-WebRequest -Uri "https://theitbros.com/test.zip" -OutFile "C:\Downloads\file.zip"
Make HTTP POST Requests
Make a POST request:
curl -d "key1=value1&key2=value2" -X POST http://service
PS:
$body = @{
"key1" = "value1"
"key2" = "value2"
}
$response = Invoke-WebRequest -Uri "http://service" `
-Method Post `
-ContentType "application/x-www-form-urlencoded" `
-Body $body Send JSON Data via POST
Post a JSON file:
curl -d "@data.json" -H "Content-Type: application/json" -X POST http://service
PS:
$body = Get-Content data.json -Raw
Invoke-RestMethod `
-Uri "http://api.service" `
-Method Post `
-ContentType "application/json" `
-Body $body
Send HTTP POST requests with JSON data:
curl.exe -X POST "https://api.service/data" `
-H "Content-Type: application/json" `
-d '{"Country":"UK","Index":220}'
PS:
$response = Invoke-WebRequest -Uri "https://api.service/data" `
-Method Post `
-ContentType "application/json" `
-Body "{`"Country`": `"UK`", `"Index`": 220}"
Authenticate with Basic Credentials
Authenticate with basic credentials:
curl -u username:password http://service PS: $username = "username" $password = ConvertTo-SecureString "password" -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($username, $password) $response = Invoke-WebRequest -Uri "http://service" ` -Credential $credential ` -Authentication Basic ` -AllowUnencryptedAuthentication
Comparing cURL vs Invoke-WebRequest in PowerShell
The key difference is not โraw text vs objectsโ, but the abstraction level. The curl.exe is a low-level HTTP client that returns raw response data, while PowerShell cmdlets like Invoke-WebRequest and Invoke-RestMethod provide structured access to response metadata and parsed content (HTML, JSON, headers).
Keep in mind that Invoke-RestMethod can automatically deserialize JSON into PowerShell objects, while curl.exe requires manual parsing of output when structured data is needed.
The difference is that Invoke-WebRequest still exposes raw content via the `.Content` property,
while curl.exe can also be parsed manually (using tools like ConvertFrom-Json when needed).
Note. In PowerShell 7+, the legacy curl alias was removed. When curl is entered, PowerShell resolves and executes curl.exe through normal command lookup rules.
Practical differences
| Feature | curl.exe | Invoke-WebRequest |
|---|---|---|
| Cross-platform behavior | consistent | PowerShell-dependent |
| Output type | raw HTTP stream | structured object |
| JSON handling | manual parsing required | better handled by Invoke-RestMethod |
| Pipeline integration | limited | strong |
| Best use case | debugging, raw HTTP | scripting, automation |
For PowerShell-based API automation, you should prefer Invoke-RestMethod option because it automatically converts JSON responses into PowerShell objects. Note that Invoke-WebRequest is better suited for working with HTML content and web pages, while curl.exe remains useful for troubleshooting, testing, and reproducing HTTP requests from vendor documentation.
Version-specific note. Keep in mind that HTML parsing behavior in Invoke-WebRequest differs between Windows PowerShell 5.1 and PowerShell 7+.
In Windows PowerShell 5.1, Invoke-WebRequest relied on the Internet Explorer (MSHTML) engine and exposed DOM-related properties (such as `.ParsedHtml`, `.Forms`, `.Links`, and `.Images`).
In PowerShell 6 and later, the dependency on Internet Explorer was removed. As a result, scripts that rely on legacy DOM parsing behavior may require updates when migrated from Windows PowerShell 5.1 to PowerShell 7+.
Is cURL installed by default on Windows?
Yes. Starting with Windows 10 version 1803 and Windows Server 2019, the native curl.exe executable is included by default and is typically located in:
C:\Windows\System32\curl.exe
You can verify that cURL is installed by running:
curl -V
How can I check what command PowerShell runs when I type curl?
Use the following command:
Get-Command curl
This shows whether PowerShell resolves curl as an alias, function, script, or executable application.
What is the difference between cURL and Invoke-WebRequest?
The main difference is the abstraction level:
- curl.exe is a low-level HTTP client that returns raw response data.
- Invoke-WebRequest returns a structured PowerShell object that includes headers, status codes, and content.
Invoke-WebRequest integrates better with PowerShell scripting and automation workflows.
Is cURL cross-platform?
Yes. cURL is available on Windows, Linux, macOS, and many Unix-based systems. This makes it useful for creating portable scripts and reproducing examples from vendor documentation across different operating systems.
