PowerShell curl -H Errors: Check the Alias Before Changing Your API Request
A curl command fails in Windows PowerShell? Identify the Invoke-WebRequest alias, use curl.exe or translate the request to a PowerShell cmdlet.
TL;DR
- In Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest, so -H and -X fail.
- Run Get-Command curl -All to confirm, then type curl.exe to use the real tool.
- Parameter-binding errors are local; a 401 or TLS warning means curl did run.
A command copied from an API tutorial works in Command Prompt, but Windows PowerShell reports that -H cannot be converted into a dictionary or that -X is not a recognised parameter. The server may not have received a request at all.
In Windows PowerShell 5.1, `curl` normally points to `Invoke-WebRequest` rather than the curl executable. The two tools accept different options. To run the command-line curl tool in Windows PowerShell, explicitly type `curl.exe`. PowerShell 7+ does not define that alias by default, though customised shells can. Microsoft confirms both behaviours in its curl on Windows guide.
This guide covers Windows 10 and Windows 11 using Windows PowerShell 5.1, PowerShell 7+, or Command Prompt. It reflects the documentation available on 8 November 2026. The examples are documentation-verified rather than executed in a Windows PowerShell session.
The command-name collision
When a shell reads a command, it decides which executable, function or alias the name represents. In Command Prompt, curl generally selects the Windows curl binary. In Windows PowerShell 5.1, the built-in alias can take precedence and call Invoke-WebRequest. Windows Terminal can host either shell, so the window title by itself cannot tell you what is running.
Native curl expects a string after -H, such as "Content-Type: application/json". In contrast, PowerShell's Invoke-WebRequest -Headers expects a mapping of header names to values. The PowerShell 5.1 Invoke-WebRequest reference documents this parameter and the separate -Method option.
Consider this illustrative curl line:
curl -X POST https://api.example.com/items -H "Content-Type: application/json" The hostname is a placeholder. If curl is an alias, PowerShell tries to bind -X and -H to a cmdlet. A parameter-binding error can appear before a network request is sent. Reinstalling a game, changing API credentials or lowering browser security is not an appropriate response.
Find out what curl means in your exact window
These commands only inspect the shell and its command resolution:
$PSVersionTable.PSVersion.ToString()
Get-Command curl -All | Format-Table CommandType, Name, Definition
Get-Command curl.exe The first returns the *PowerShell engine version*, not the Windows release. The second shows candidates in precedence order. If it reports Alias curl -> Invoke-WebRequest, the collision is present. Microsoft's Get-Command documentation explains why the -All option helps with duplicate command names.
The last check asks whether a native curl.exe executable is available. Two additional checks are useful:
where.exe curl
curl.exe --version The explicit .exe matters. Bare where can refer to a PowerShell alias. curl.exe --version should print information about the native program, independent of the curl alias. If the executable is missing, investigate its installation and the process's PATH; do not turn off script security settings.
Different Windows Terminal tabs can host different shells. Recheck in the tab that actually failed rather than assuming one terminal application's settings apply to every tab.
Diagnose the right failure
| Symptom | What it usually means | Next check |
|---|---|---|
| `curl -H` cannot convert a string to a dictionary | The PowerShell alias is calling Invoke-WebRequest, whose Headers parameter needs a dictionary | Use Get-Command curl -All, then curl.exe |
| `curl -X` is not recognised | The cmdlet is parsing native curl's flags | Inspect the shell and command name before changing the request |
| `curl --version` does not print a version | curl resolves to an alias or function | Run curl.exe --version |
| A Script Execution Risk confirmation appears | Windows PowerShell 5.1 has entered Invoke-WebRequest's legacy HTML-parsing path | Use -UseBasicParsing on the cmdlet or call curl.exe |
| `curl.exe` cannot be found | No native executable was found through this session's path | Try Get-Command curl.exe and where.exe curl |
| HTTP 401 or a TLS error appears | The client ran and a separate network, authentication or trust issue remains | Inspect the response; keep TLS validation on |
A parameter-binding error is a local shell issue. A returned HTTP 401, a server error, or a TLS certificate warning is not. Once you have selected the intended program, read its actual response instead of assuming that every problem mentioning curl has the same cause.
Use native curl when following curl documentation
If the original instructions use -I, -H, -X or --data-binary, the least surprising repair in Windows PowerShell is to spell the executable name:
curl.exe --version
curl.exe -I https://example.com/ The -I flag requests HTTP response headers. The example still needs connectivity, a trusted server certificate, and a server willing to respond. Microsoft's Windows curl page and the upstream curl manual document these commands.
Send JSON without fragile inline quotation marks
Linux shell recipes often contain single-quoted JSON strings. PowerShell's interaction with native argument parsing can make copying them harder than expected, particularly across versions. A file-based request avoids a layer of nested quoting. First make a tiny, ASCII-only demonstration file in a directory where you have write permission:
'{"name":"widget","quantity":1}' | Set-Content -LiteralPath .\request.json -Encoding ASCII
Get-Content -Raw -LiteralPath .\request.json Inspect the content before the POST. The following is an illustrative template, not a working request; replace the API hostname with a test endpoint you control or are authorised to use:
curl.exe --request POST "https://api.example.com/items" `
--header "Content-Type: application/json" `
--data-binary "@request.json" A backtick at the very end of a line continues a command in PowerShell. In Command Prompt, use one line or that shell's own continuation rules. The curl --data-binary documentation explains how it reads a file and sends its bytes without discarding line breaks.
Encoding warning: -Encoding ASCII is appropriate only for this deliberately ASCII sample. It cannot represent arbitrary Unicode. For multilingual production data, create and verify a valid UTF-8 request file with a suitable editor or no-BOM writer; Windows PowerShell 5.1 and PowerShell 7 do not handle every -Encoding option identically.
After checking your request, remove the disposable sample if you no longer need it:
Remove-Item -LiteralPath .\request.json Curl completing a request is not proof the API accepted it. Inspect the HTTP status and any response body rather than mistaking all output for success.
Use PowerShell cmdlets when you want PowerShell behaviour
For scripted API calls, Invoke-RestMethod can be more convenient: it converts JSON responses to PowerShell objects. A simple GET looks like this:
$result = Invoke-RestMethod -Uri 'https://example.com/' -Method Get
$result A sample POST uses a hashtable for headers and explicitly serialises the body:
$headers = @{ 'X-Request-Source' = 'manual-test' }
$body = @{ name = 'widget'; quantity = 1 } | ConvertTo-Json -Compress
Invoke-RestMethod -Uri 'https://api.example.com/items' `
-Method Post `
-Headers $headers `
-ContentType 'application/json' `
-Body $body Again, replace the placeholder URL with your own API before executing. Here -Headers is a dictionary, -ContentType specifies JSON, and -Body contains JSON text. Microsoft's Invoke-RestMethod documentation explains automatic parsing and parameter behaviour. The basic syntax works for ordinary requests; advanced options may depend on the PowerShell version.
When the goal is downloading software, Invoke-WebRequest -OutFile can be a suitable cmdlet instead. If the publisher supplies an expected SHA-256 hash, verify the downloaded file before installing it. Jitsumi's Windows SHA-256 verification walkthrough shows how to check the complete hash. Matching a reference supports file-integrity checking; it does not establish that an unknown publisher is trustworthy.
A separate 2025 security prompt can confuse the issue
There is a newer complication for Windows PowerShell 5.1. With Windows updates released on or after 9 December 2025, Microsoft introduced a Script Execution Risk confirmation for the legacy HTML-parsing path in Invoke-WebRequest. Someone who thinks they invoked curl but actually invoked the alias can encounter that prompt unexpectedly.
Microsoft's security advisory originally published 9 December 2025 explains that the older path used Internet Explorer components that could execute page scripts. For genuine Invoke-WebRequest use, Microsoft's recommended safer approach is:
Invoke-WebRequest -Uri 'https://example.com/' -UseBasicParsing In unattended Windows PowerShell 5.1 scripts, make that safe option explicit so a confirmation does not hold an automated job waiting for input. PowerShell 7 does not depend on the Internet Explorer HTML parser. Calling native curl.exe also avoids this specific cmdlet warning when the native program is what you intended. Do not blindly approve a warning simply to make a command finish.
Avoid changes that fix the wrong thing
A curl header-binding error does not require changing PowerShell execution policy. That policy concerns running scripts. For a .ps1 file blocked by an execution-policy error, Jitsumi has a separate PowerShell script-policy guide.
You also do not need to delete aliases permanently. Microsoft documents Remove-Item Alias:curl as a possible session-level workaround, but writing curl.exe is more explicit and does not change how other commands resolve in that window.
Do not add native curl's -k or --insecure switch to repair an alias error. Those flags turn off TLS certificate verification and can hide a separate certificate or trust problem. If curl.exe reports a genuine TLS error, investigate the reported cause while leaving verification on.
Avoid exposing real access tokens and passwords in pasted commands, shell history, screenshots and support tickets. Use a disposable test credential where possible, and redact secrets when sharing logs.
Check the outcome before moving on
After choosing a tool, rerun a harmless request and verify three things: command resolution identifies the intended program, the local parameter-binding error has disappeared, and the server's HTTP status and response body match expectations. If you now receive a 401 or TLS error, you have solved the alias issue but reached a different problem.
The distinction to remember is simple: `curl.exe` uses curl flags; `Invoke-WebRequest` and `Invoke-RestMethod` use PowerShell parameters.
Subscribe
All the new articles in one Monday digest. Unsubscribe with one click.