できない.dev

PowerShell で curl のオプションが効かない(Invoke-WebRequest の別名)

Windows PowerShell 5.1 では curl は Invoke-WebRequest の別名で、-I や -o といった本家のオプションを解釈しない。
curl.exe と拡張子まで書いて呼ぶか、cmdlet 側のパラメータに読み替える。

公開: 更新:

症状できない
Get-Command curl | Format-List Name, CommandType, Definition
Name        : curl
CommandType : Alias
Definition  : Invoke-WebRequest

2026-10-03 に local host (Windows 11 Home, Docker 29.8.0)(Node.js 22.14.0 / npm 10.9.2) で実際に打って取った出力。検証環境の詳細

要約

Windows PowerShell 5.1 の curl は本家の curl ではない。Invoke-WebRequest のリファレンス(新しいタブで開く) が「Windows PowerShell includes the following aliases」として iwr / curl / wget を挙げているとおり、cmdlet への別名である。

PS> curl -I https://example.com
Invoke-WebRequest : Cannot process command because of one or more missing mandatory parameters: Uri.

-I はヘッダのみ取得する curl のオプションだが、PowerShell はこれをパラメータ名の前方一致として扱い -InFile に結び付ける。
続く URL はそのファイル名として吸われるため、位置引数の -Uri が埋まらず、URL を渡したはずなのに「Uri が無い」と言われる。

実行例

Windows 11 の Windows PowerShell 5.1 で curl を解決すると CommandType : Alias・Definition : Invoke-WebRequest になり、curl -I https://example.com は必須パラメーター Uri が指定されていないという Invoke-WebRequest のエラーで止まった。curl.exe -sI は HTTP/1.1 200 OK のヘッダを返し、Invoke-WebRequest -Method Head の StatusCode は 200、Remove-Item Alias:curl のあとは curl.exe(Application)に解決されている。

$ Get-Command curl | Format-List Name, CommandType, Definition
Name        : curl
CommandType : Alias
Definition  : Invoke-WebRequest
$ curl -I https://example.com
Invoke-WebRequest : コマンドを処理できません。次の 1 つ以上の必須パラメーターが指定されていません:  Uri。
発生場所 行:1 文字:1
+ curl -I https://example.com
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Invoke-WebRequest]、ParameterBindingException
    + FullyQualifiedErrorId : MissingMandatoryParameter,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
$ curl.exe -sI https://example.com
HTTP/1.1 200 OK
Date: Sat, 03 Oct 2026 01:44:21 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Server: cloudflare
last-modified: Fri, 02 Oct 2026 16:11:13 GMT
allow: GET, HEAD
Accept-Ranges: bytes
Age: 5552
cf-cache-status: HIT
CF-RAY: a44842e07ae6d4ab-NRT
alt-svc: h3=":443"; ma=86400
$ (Invoke-WebRequest -Uri https://example.com -Method Head -UseBasicParsing).StatusCode
200
$ Remove-Item Alias:curl; Get-Command curl | Format-List Name, CommandType, Definition
Name        : curl.exe
CommandType : Application
Definition  : C:\WINDOWS\system32\curl.exe

— 2026-10-03 時点の出力

検証環境Node.js 22.14.0 / npm 10.9.2 / Git 2.48.1.windows.1 / 2026-10-03 検証(ほか 1 件)
検証日
実行環境
local host (Windows 11 Home, Docker 29.8.0)
バージョン
  • Node.js 22.14.0
  • npm 10.9.2
  • Git 2.48.1.windows.1
  • Docker 29.8.0

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

解決策

1. curl.exe と書く

curl.exe -I https://example.com
curl.exe -sSL -o out.zip https://example.com/file.zip

拡張子まで書けば別名は当たらず、本家の curl がそのまま動く。
手順書を移植するときはこれが最短である。

2. いま何に解決されているか確かめる

Get-Command curl | Format-List Name, CommandType, Definition
Name        : curl
CommandType : Alias
Definition  : Invoke-WebRequest

CommandType が Alias なら別名、Application なら実行ファイルである。
5.1 と 7 のどちらで動かしているかを推測せずに済む。

3. cmdlet のパラメータへ読み替える

Invoke-WebRequest -Uri https://example.com -Method Head -UseBasicParsing
Invoke-WebRequest -Uri https://example.com/file.zip -OutFile out.zip -UseBasicParsing

-I は -Method Head、-o は -OutFile に対応する。
5.1 では -UseBasicParsing も付けて、確認プロンプトを避ける。

4. 別名を外す

Remove-Item Alias:curl

そのセッションでだけ別名が消え、curl が curl.exe へ解決されるようになる。Remove-Alias は PowerShell 6.0 で追加された cmdlet なので、5.1 では上の書き方を使う。

5. スクリプトでは名前を固定する

共有するスクリプトに curl とだけ書くと、実行者のバージョンで意味が変わる。curl.exe か Invoke-WebRequest のどちらかに寄せておけば、この曖昧さは残らない。

よくある原因

  1. 別名の優先度: PowerShell は同名の別名と実行ファイルがあれば別名を先に選ぶ。
    Windows 10 以降には C:\Windows\System32\curl.exe が同梱されているが、curl と打つ限りそちらは呼ばれない。
  2. 前方一致でパラメータに化ける: PowerShell はパラメータ名の省略を前方一致で解決する。-I は -InFile に一致してしまうので、存在しないオプションを渡したときのような「そんなパラメータは無い」というエラーにはならない。-Q のようにどれにも一致しない場合だけ別のメッセージが出る。
    原因の切り分けが遅れやすい。
  3. 手順書の使い回し: Linux / macOS 向けの curl -sSL ... | sh のような 1 行を、そのまま PowerShell の窓へ貼っている。
  4. バージョン差: PowerShell 7 系にこの別名は無く、curl は素直に curl.exe へ解決される。
    7 で検証した手順が 5.1 で落ちる。
  5. 解析の既定が変わった: 2025 年 12 月のセキュリティ更新(CVE-2025-54100)以降、5.1 の Invoke-WebRequest は -UseBasicParsing を付けないと確認プロンプトを出す。
    スクリプトの中では応答できず、そこで止まる。

この手順で直った?