NTLM still appears on IIS applications, Windows-backed intranet APIs, and other legacy HTTP endpoints that expect a domain account instead of a browser session. When the same protected endpoint needs to be tested from a terminal, curl can complete the NTLM challenge-response exchange directly.
An NTLM-protected origin server usually answers the first unauthenticated HTTP/1.1 request with 401 Unauthorized and a WWW-Authenticate: NTLM header. In curl, --ntlm selects NTLM for the origin server, and --user supplies the account in DOMAIN\username:password or user@example.com:password form.
NTLM is best treated as a compatibility path rather than a preferred long-term authentication method. Keep it on HTTPS, avoid leaving reusable passwords on the literal command line when possible, and use the proxy-authentication path when the challenge is 407 Proxy Authentication Required with Proxy-Authenticate: NTLM. Minimal curl builds may also lack the NTLM or TLS support required for --ntlm, which appears as an unsupported feature rather than a bad password.
$ curl --silent --show-error --verbose --output /dev/null https://api.example.net/reports/weekly-summary * Host api.example.net:443 was resolved. ##### snipped ##### > GET /reports/weekly-summary HTTP/1.1 > Host: api.example.net > Accept: */* < HTTP/1.1 401 Unauthorized < WWW-Authenticate: NTLM ##### snipped #####
A 401 plus WWW-Authenticate: NTLM means the origin server is asking for NTLM. If the response is 407 Proxy Authentication Required with Proxy-Authenticate: NTLM, the proxy is challenging first and the proxy-authentication path is the correct next step.
$ curl --silent --show-error --ntlm --user 'OPS\svc-report-readonly:REDACTED_NTLM_PASSWORD' --write-out '\nHTTP %{http_code}\n' https://api.example.net/reports/weekly-summary
{
"report": "weekly-summary",
"status": "ok",
"authenticated_as": "OPS\\svc-report-readonly"
}
HTTP 200
Inline credentials are easy to copy into notes, shell history, terminal scrollback, and process listings, so use this form for short local tests rather than long-lived automation.
$ curl --silent --show-error --ntlm --user 'OPS\svc-report-readonly' --write-out '\nHTTP %{http_code}\n' https://api.example.net/reports/weekly-summary
Enter host password for user 'OPS\svc-report-readonly':
{
"report": "weekly-summary",
"status": "ok",
"authenticated_as": "OPS\\svc-report-readonly"
}
HTTP 200
The interactive prompt keeps the password out of the shell history, but it is not suitable for unattended jobs. For repeatable automation, store the credential in a private cURL config or netrc file instead of retyping it.
$ curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' --ntlm --user 'OPS\svc-report-readonly:REDACTED_NTLM_PASSWORD' https://api.example.net/reports/weekly-summary
200
A repeated 401 usually means the username, password, domain prefix, or upstream account mapping is wrong rather than a generic curl syntax problem.
$ curl --silent --show-error --verbose --ntlm --user 'OPS\svc-report-readonly:REDACTED_NTLM_PASSWORD' --output /dev/null https://api.example.net/reports/weekly-summary * Host api.example.net:443 was resolved. ##### snipped ##### * Server auth using NTLM with user 'OPS\svc-report-readonly' > GET /reports/weekly-summary HTTP/1.1 > Host: api.example.net > Authorization: NTLM ***REDACTED_NTLM_TOKEN*** > Accept: */* < HTTP/1.1 401 Unauthorized < WWW-Authenticate: NTLM ***REDACTED_NTLM_CHALLENGE*** ##### snipped ##### * Server auth using NTLM with user 'OPS\svc-report-readonly' > Authorization: NTLM ***REDACTED_NTLM_TOKEN*** ##### snipped ##### < HTTP/1.1 200 OK
Verbose output exposes NTLM tokens and request metadata, so keep traces local and redact them before sharing. Related: How to debug HTTP requests with cURL
Related: View request headers in cURL