How do I get the body of a web request that returned 400 Bad Request from Invoke-RestMethod

invoke-restmethod get parameters
the remote server returned an error: (400) bad request.
invoke-webrequest vs invoke-restmethod
invoke webrequest exception get body
invoke-restmethod : the remote server returned an error
invoke-restmethod splatting
invoke-restmethod authentication

When I run the following statement

Invoke-RestMethod "" `
    -Body (ConvertTo-Json $data) `
    -ContentType "application/json" `
    -Headers $DefaultHttpHeaders `
    -Method Post

the endpoint returns 400 Bad Request, which causes PowerShell to show the following not-so-helpful message:

Invoke-WebRequest : The remote server returned an error: (400) Bad Request.
At line:1 char:1
+ Invoke-WebRequest "" -Body  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

How do I get the body of the response, which might tell me what was wrong with the request I sent?

According to Invoke-RestMethod documentation, cmdlet can return different types depending on the content it receives. Assing cmdlet output to a variable ($resp = Invoke-RestMethod (...)) and then check if the type is HtmlWebResponseObject ($resp.gettype()). Then you'll have many properties at your disposal, like BaseResponse, Content and StatusCode.

If $resp is some other type (string, psobject and most probably null in this case), it seems that error message The remote server returned an error: (400) Bad Request is the response body, only stripped from html (I tested this on some of my methods), maybe even truncated . If you want to extract it, run the cmdlet using common parameter to store the error message: Invoke-RestMethod (...) -ErrorVariable RespErr and you'll have it in $RespErr variable.


Ok, I got it and it was pretty obvious :). Invoke-RestMethod throws an error, so lets just catch it:

try{$restp=Invoke-RestMethod (...)} catch {$err=$_.Exception}
$err | Get-Member -MemberType Property

  TypeName: System.Net.WebException

    Name           MemberType Definition
    ----           ---------- ----------
    Message        Property   string Message {get;}
    Response       Property   System.Net.WebResponse Response {get;}
    Status         Property   System.Net.WebExceptionStatus Status {get;}

Here's all you need, especially in WebResponse object. I listed 3 properties that catch the eye, there's more. Also if you store $_ instead of $_.Exception there could be some properties PowerShell already extracted for you, but I don't expect nothing more meaningful than in .Exception.Response.

Invoke-RestMethod : The remote server returned an , Follow how-do-i-get-the-body-of-a-web-request-that-returned-400-bad-request-​from-invoke to get more details of the error. 2. Check your code  400 Bad Request errors appear differently on different websites, so you may see something from the short list below instead of just 400 or another simple variant like that:

There is a known issue with PowerShell Invoke-WebRequest and Invoke-RestMethod where the shell eats the response body when the status code is an error (4xx or 5xx). Sounds like the JSON content you are looking for is evaporating in just this manner. You can fetch the response body in your catch block using $_.Exception.Response.GetResponseStream()

    try {
    Invoke-RestMethod "" `
        -Body (ConvertTo-Json $data) `
        -ContentType "application/json" `
        -Headers $DefaultHttpHeaders `
        -Method Post
    catch {
        $streamReader = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
        $ErrResp = $streamReader.ReadToEnd() | ConvertFrom-Json


REST API Explorer, Unfortunately the request body for the above code is malformed and is Invoke-​WebRequest : The remote server returned an error: (400) Bad  I'm looking over the documentation, try to run this request using the SiteID instead of the domain? You can get your site ID by viewing your site, viewing source, then searching for 'blog='. It will be an integer about 8 digits long.

$RespErr will have the more details about the BadRequest in my case its

$responce = Invoke-RestMethod -Uri https://localhost:44377/explore/v2/Content -Method Post -Body $PostData -Headers $header -ErrorVariable RespErr;


{ "error":{ "code":"","message":"The FavoriteName field is required." } }

It looks like it works only in localhost, i tried with my actual server it didn't work.

another way to try is this

$response = ""
$response = Invoke-WebRequest -Uri -Method Post -Body $PostData -Headers  $header -ErrorVariable RespErr 
#$response = Invoke-RestMethod -Uri https://localhost:44377/explore/v2/Content?overwrite=true -Method Post -Body $PostData -Headers  $header -ErrorVariable RespErr 
Write-Host "Content created with url="$response.value[0] 

catch [System.Net.WebException] {   
        $respStream = $_.Exception.Response.GetResponseStream()
        $reader = New-Object System.IO.StreamReader($respStream)
        $respBody = $reader.ReadToEnd() | ConvertFrom-Json

Invoke-WebRequest CloudFlare API Error 400, -Method PUT -Headers $headers -Body $body).Content. The output I get is: Invoke-RestMethod : The remote server returned an error: (400) Bad Request. Invoke-RestMethod : The remote server returned an error: (400) Bad Request. Follow how-do-i-get-the-body-of-a-web-request-that-returned-400-bad-request-from

If you are just after the response StatusCode and Content here is a novel way of solving this problem without lots of messy try/catch and manual reading of response streams:

# Place the trap within your chosen scope (e.g. function or script)
trap [Net.WebException] { continue; }

# Exceptions are no longer thrown here
$response = Invoke-WebRequest $endpoint

# Check if last command failed
if (!$?)
    # $error[0] now contains the ErrorRecord of the last error (in this case from Invoke-WebRequest)
    # Note: $response should be null at this point

    # Due to the magic of Microsoft.PowerShell.Commands.InvokeWebRequestCommand.WebCmdletWebResponseException
    # we can get the response body directly from the ErrorDetails field
    $body = $error[0].ErrorDetails.Message

    # For compatibility with $response.StatusCode lets cast to int    
    $statusCode = [int] $error[0].Exception.Response.StatusCode

As far as I can tell, the ErrorRecord.ErrorDetails.Message contains the exact equivalent to the Microsoft.PowerShell.Commands.WebResponseObject.Content property that would get returned to you on a successful invocation of Invoke-WebRequest, just without the hassle of having to do all that GetResponseStream() jazz.

Invoke-WebRequest Bad Request using Rest API, Invoke-WebRequest : The remote server returned an error: (400) Bad Request. At line:1 char:2 + (Invoke-WebRequest -Credential  How do I get the body of a web request that returned 400 Bad Request from Invoke-RestMethod. 1. Missing API key when making API RestMethod Call After HTTP Basic

For me it only worked in a Pester context, when setting the streams Position to 0 before reading it.

        $statusCode = $null
        $responseBody = $null
        try {
            $response = Invoke-RestMethod -Method GET -Uri "$($apiPrefix)$($operation)" -Headers $headers
        catch [System.Net.WebException] {
            $statusCode = $_.Exception.Response.StatusCode
            $respStream = $_.Exception.Response.GetResponseStream()
            $reader = New-Object System.IO.StreamReader($respStream)
            $reader.BaseStream.Position = 0
            $responseBody = $reader.ReadToEnd() | ConvertFrom-Json
        $statusCode | Should Be $Expected
        $responseBody | Should Not Be $null

Solved: Extended Latin and 400 Bad Request, I use powershell Invoke-RestMethod command and generate a body on the fly. I receive "The remote server returned an error: (400) Bad Request" response. Click to share on Twitter (Opens in new window) Click to share on Facebook (Opens in new window)

Mastering Windows PowerShell Scripting: One-stop guide to , Requests with arguments Arguments are passed to REST methods in one of two possible ways: in a query string or using the Body parameter. Web $address = '​221b Baker St, Marylebone, London NW1 6XE' $address = [System.Web. $​body Invoke-RestMethod : The remote server returned an error: (400) Bad Request. The Invoke-WebRequest cmdlet sends HTTP and HTTPS requests to a web page or web service. It parses the response and returns collections of links, images, and other significant HTML elements. This cmdlet was introduced in PowerShell 3.0. Beginning in PowerShell 7.0, Invoke-WebRequest supports proxy configuration defined by environment variables. See the Notes section of this article.

Powershell RESTAPI newbie - Add a host record, Invoke-RestMethod : The remote server returned an error: (400) Bad this code snip around your request to display the returned error body:. The format you are showing in the body doesn’t look valid. Valid JSON looks like this: { “key”: “value”, “another_key”: “another value” } If you try to post invalid formatted JSON the receiving server will respond with a 400 bad request HTTP status code. Google valid JSON and you’ll find more details regarding proper formatting.

Invoke-RestMethod : The remote server returned an error: (400) Bad , Getting the following error: Invoke-RestMethod : The remote server returned an error: (400) Bad Request. What am i doing wrong? Works for a  You can pipe the body of a web request to Invoke-RestMethod. Outputs. System.Int64, System.String, System.Xml.XmlDocument. The output of the cmdlet depends upon the format of the content that is retrieved. PSObject. If the request returns JSON strings, Invoke-RestMethod returns a PSObject that represents the strings. Notes