What changes between curl and HttpClient
The generated code sends the same request, but a few defaults differ, and they explain most "it works in curl but not in my app" bugs. We found each of these by sending the same request both ways:
- curl sends default headers of its own:
User-Agent: curl/<version>andAccept: */*. HttpClient sends neither, and APIs that require a User-Agent (GitHub's does) reject HttpClient's request. Tick the option above to add them. new StringContent(json, Encoding.UTF8, "application/json")sendsapplication/json; charset=utf-8, adding a charset curl does not send. The overload that takes aMediaTypeHeaderValuesends the type exactly, which is what the converter uses.request.Headers.TryAddWithoutValidation("Content-Type", ...)returns false and the header is silently not sent, because Content-Type belongs onrequest.Content.Headers.- curl follows redirects only with
-L; HttpClient always does, drops theAuthorizationheader on the way (even for the same host), and turns POST into GET after 301, 302 and 303. - HttpClient stores cookies from responses and sends them on later requests to the same host, and it merges them with a Cookie header you set yourself. curl does neither without a cookie jar. The converter sets
UseCookies = falsewhen the command has-b. - curl sends non-ASCII header values as UTF-8; HttpClient throws "Request headers must contain only ASCII characters" unless you set
RequestHeaderEncodingSelector, which the converter adds when needed. curl -d "q=a b"sends the space as is, since-ddoes not encode. Use--data-urlencode(orFormUrlEncodedContentin C#) for values that need encoding. And-d @filestrips the file's line breaks, while--data-binary @filekeeps them.
Reuse the HttpClient
The simple version creates an HttpClient to keep the example short. In an application, create one and reuse it, or let IHttpClientFactory manage the handlers: creating a client per request can exhaust sockets, and a single client that lives forever does not see DNS changes. The IHttpClientFactory tab gives you a typed client registered with AddHttpClient.
FAQ
Why does my API accept the curl command but reject the same request from HttpClient?
Usually the missing User-Agent, a charset added to the Content-Type, or the Authorization header lost on a redirect. See the list above.
How do I send JSON with HttpClient like curl -d?
new StringContent(json, Encoding.UTF8, new MediaTypeHeaderValue("application/json")) sends the text exactly; PostAsJsonAsync serializes an object for you.
Does HttpClient follow redirects like curl -L?
Always, unless you set AllowAutoRedirect = false on the handler. It drops Authorization on the redirect and turns POST into GET after 301, 302 and 303.
How do I convert curl -F file uploads to C#?
With MultipartFormDataContent: a StringContent per field, a StreamContent with its Content-Type and file name per file.
Can I paste the curl command Chrome copies on Windows?
Yes, both "Copy as cURL (bash)" and "Copy as cURL (cmd)" work.
Related tools
Learn more
- How to Send a JSON Object Using HttpClient in .NET
- How to Add a BearerToken to an HttpClient Request
- How to Use Basic Authentication With HttpClient?
- Add a Cookie to an HttpClient Request/Response in ASP.NET Core
- HttpClient Default Timeout in C# and How to Change It
- How to Set a Default User-Agent on an HttpClient in ASP.NET Core