Try this:
try { $response = Invoke-WebRequest http://localhost/foo } catch {
$_.Exception.Response.StatusCode.Value__}
It is kind of a bummer that this throws an exception but that's the way it is.
Update per comments
To ensure that such errors still return a valid response, you can capture those exceptions of type WebException and fetch the related Response.
Since the response on the exception is of type System.Net.HttpWebResponse, whilst the response from a successful Invoke-WebRequest call is of type Microsoft.PowerShell.Commands.HtmlWebResponseObject, to return a compatible type from both scenarios we need to take the successful response's BaseResponse, which is also of type System.Net.HttpWebResponse.
This new response type's status code is an enum of type [system.net.httpstatuscode], rather than a simple integer, so you have to explicity convert it to int, or access its Value__ property as described above to get the numeric code.
#ensure we get a response even if an error's returned
$response = try {
(Invoke-WebRequest -Uri 'localhost/foo' -ErrorAction Stop).BaseResponse
} catch [System.Net.WebException] {
Write-Verbose "An exception was caught: $($_.Exception.Message)"
$_.Exception.Response
}
#then convert the status code enum to int by doing this
$statusCodeInt = [int]$response.BaseResponse.StatusCode
#or this
$statusCodeInt = $response.BaseResponse.StatusCode.Value__