invoke-webrequest — PowerShell's HTTP cmdlet — the curl / wget equivalent across all 5 shells
Equivalents in every shell
curl https://example.com`curl` writes the response body to stdout by default. Common flags: `-L` follows redirects, `-o file` writes to disk, `-X POST -d 'key=val'` posts form data, `-H 'Content-Type: application/json' -d '{}'` posts JSON. `wget url` is the alternative; wget defaults to writing the response to a file with the URL's tail as the name.
curl https://example.comSame external `curl`. macOS ships curl linked against the system Secure Transport TLS stack (different trust roots than Linux's OpenSSL builds); newer macOS versions also ship `curl --version` ≥ 8.x with HTTP/2 support. Linux distros use OpenSSL or GnuTLS-linked curl.
curl https://example.comSame external. Fish has cleaner quoting for URLs with shell-special characters — `curl 'https://example.com/path?key=val&other=val2'` works without backslashes because fish doesn't expand `&` inside single quotes.
Invoke-WebRequest https://example.comPowerShell-native HTTP client (aliases `iwr`, `curl`, `wget` — but the latter two are PowerShell-specific aliases, NOT the real binaries). Returns a `[BasicHtmlWebResponseObject]` with `.Content`, `.StatusCode`, `.Headers`, `.Links`, `.Images`, `.Forms`. For JSON APIs `Invoke-RestMethod` is the sibling that auto-parses JSON into PSObjects.
curl https://example.comWindows 10 1803+ ships `curl.exe` natively in `C:\Windows\System32`. Identical to Unix curl. Older Windows installs have no HTTP client — use PowerShell `Invoke-WebRequest`, or call .NET via `cscript`.
Worked examples
GET a URL and write the response body to disk
curl -L https://example.com/file.zip -o file.zipInvoke-WebRequest https://example.com/file.zip -OutFile file.zipcurl -L https://example.com/file.zip -o file.zipPOST JSON to an API
curl -X POST -H 'Content-Type: application/json' -d '{"name":"alice"}' https://api.example.com/usersInvoke-RestMethod -Method POST -Uri https://api.example.com/users -Body (@{name='alice'} | ConvertTo-Json) -ContentType 'application/json'Follow redirects and capture the response status code
curl -L -o /dev/null -s -w '%{http_code}\n' https://example.com(Invoke-WebRequest https://example.com -MaximumRedirection 5).StatusCodeGotchas
- On Windows PowerShell 5.1, `Invoke-WebRequest` defaults to PARSING the HTML response with `mshtml.dll` (the Internet Explorer engine) — this is VERY slow on big pages and fails outright if IE is uninstalled. Always pass `-UseBasicParsing` on PS 5.1. PowerShell 7+ removed the legacy parsing path; `-UseBasicParsing` is then a no-op but still accepted.
- `-SkipCertificateCheck` is PowerShell 7-only. On PS 5.1, to ignore TLS errors (testing only), you must hack the GLOBAL `ServicePointManager` callback: `[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }`. This sets the validator process-wide — never ship it in production scripts; isolate to a one-shot session.
- `Invoke-WebRequest` follows redirects up to `-MaximumRedirection 5` BY DEFAULT (curl follows ONLY when given `-L`). Scripts ported from curl that assume no-follow break when the server starts returning 301/302. To match curl's default, set `-MaximumRedirection 0`.
- `Invoke-RestMethod` AUTO-PARSES JSON responses into `[PSCustomObject]` graphs — but for non-JSON content types (XML, HTML) it returns the raw string. Some APIs return `Content-Type: application/octet-stream` even for JSON; in that case `Invoke-WebRequest` is safer (gives you the raw body to `ConvertFrom-Json` manually).
- Both cmdlets load the ENTIRE RESPONSE BODY into memory before returning — for multi-GB downloads prefer `-OutFile` (streams to disk) or shell out to `curl.exe` with a progress meter. There is no built-in chunked-stream API in 5.1 / 7 — `-ResponseHeadersVariable` gets you headers but the body is still fully buffered.
WSL & PowerShell Core notes
Common tasks using invoke-webrequest
- Check if a URL is reachable
Test whether a URL returns 2xx/3xx — useful for healthchecks, wait-for-it scripts, and CI smoke tests.
- Check SSL certificate expiry
Print the notBefore / notAfter dates of a remote site's TLS certificate (or a local .pem file).
- Follow HTTP redirects
Print the redirect chain (301/302/303/307/308 hops) from a starting URL to its final 2xx destination.
- Get HTTP response headers
Inspect just the response headers of a URL — useful for debugging redirects, caching, CORS, and TLS.
- Retry a command on failure
Re-run a command until it succeeds or a retry cap is hit — useful for flaky network calls and CI race conditions.
- Send an HTTP POST request
POST a JSON body (or form fields, or a file) to a URL and capture the response.