Can I check for specific HTTP Response codes with PRTG?


There is no native sensor within PRTG which can do this but you may use the following Powershell script variant to use with an EXE/Script Advanced sensor:

<#
	.SYNOPSIS
		Query an HTTP Endpoint to Measure the Response Time and the HTTP Status Code

	.DESCRIPTION
		This script is able to query an HTTP/HTTPS Endpoint and measure the response time as well as the HTTP Status Code. The script is designed to be used with PRTG Network Monitor (https://www.paessler.com/prtg).

	.PARAMETER Url
		The Uniform Resource Locator (URL) you want to query, including the protocol (and path).: https://example.org or http://example.com:8080/myfile.htm

	.PARAMETER Timeout
		The number of seconds to wait for the HTTP query to complete (Default: 30)

	.PARAMETER TrustAllCerts
		Use this option to ignore any SSL Certificate issues and use all possible protocol versions

	.EXAMPLE
		Running the script interactively to test it:
		PS> .\Get-HTTPStatusCode.ps1 -Url "https://example.org/" -Timeout 10

	.EXAMPLE
		For running the script in PRTG, you can use PRTG's placeholders to make the setup more robust:
		Parameters(in the Sensor's settings): -Url "https://%host/" -Timeout 10

		However, it's also possible to enter the full URL in the sensor as expected:
		Parameters(in the Sensor's settings): -Url "https://example.org/" -Timeout 10

	.EXAMPLE
		If you're monitoring an endpoint with an invalid certificate (expired, self-signed, etc) you can enable the TrustAllCerts switch, like this:
		PS> .\Get-HTTPStatusCode.ps1 -Url "https://invalidsslserver.example.org/" -Timeout 10 -TrustAllCerts

	.NOTES
		Version: 2.5.20230920
		Author: Luciano Lingnau, Paessler AG (https://www.paessler.com/)

	.LINK
		https://kb.paessler.com/en/topic/47373
#>

#Requires -Version 3.0

param(
	[Parameter(Mandatory=$true)]
	[string]$Url,
	[int]$Timeout = "30",
	[switch]$TrustAllCerts = $false
)

[string]$sensorMessage = ''
$errorFlag = $false
$results = @()

#Avoid issues with weird SSL Certificates (Self-signed, expired, etc)
#Should only be used when a trusted certificate is not an option
if ($TrustAllCerts){
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@

#Define Accepted SSL/TLS Versions, if unset this will be differentl depending on the OS and PS Version
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12,Tls13'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}

try {
	#Stopwatch used to time the lenghtiest part of the execution (long execution times could be an issue)
	$exectime = [System.Diagnostics.Stopwatch]::StartNew()

	$a = Invoke-WebRequest -Uri $Url -TimeoutSec $Timeout -UseBasicParsing -ErrorAction SilentlyContinue

	#Stop Stopwatch used to time the lenghtiest part of the execution
	$exectime.Stop()

	#Parse the results in a PRTG Friendly way
	if ($a.StatusCode){
		$results += @{
			Channel = 'Status Code'
			Value = $a.StatusCode
			valuelookup = 'prtg.standardlookups.http.statuscode'
		}
		$results += @{
			Channel = 'Length'
			Value = $a.RawContentLength
			Unit = 'BytesFile'
		}
		$results += @{
			Channel = 'Execution Time'
			Value = $exectime.ElapsedMilliseconds
			Unit = 'TimeResponse'
		}
	}

    $sensorMessage = "$($url)"

} catch {

	#If there is a valid statuscode in the response (like 3XX) we want that to be a sensor result, so this has to be handled in the try/catch

    if ($_.Exception.Response.StatusCode.Value__ -gt 0){

		#Parse the results in a PRTG Friendly way
		$results += @{
			Channel = 'Status Code'
			Value = $_.Exception.Response.StatusCode.Value__
			valuelookup = 'prtg.standardlookups.http.statuscode'
		}
		$results += @{
			Channel = 'Length'
			Value = '-1'
		}
		$results += @{
			Channel = 'Execution Time'
			Value = $exectime.ElapsedMilliseconds
			Unit = 'TimeResponse'
		}
		
		$sensorMessage = "$($url)"

	}else{

		#Otherwise it's an exception that doesn't have a valid result

		$errorFlag  = $true
		$sensorMessage = "Exception (Line $($_.InvocationInfo.ScriptLineNumber)): $($_.Exception.Message)"
	}

}

$sensorResult = '' | Select-Object prtg
if ($errorFlag) {
	$sensorResult.prtg = '' | Select-Object error
	$sensorResult.prtg.error = 1
} else {
	$sensorResult.prtg = '' | Select-Object result
	$sensorResult.prtg.result = $results
}
if ($sensorMessage) {
	$sensorResult.prtg | Add-Member -MemberType NoteProperty -Name 'text' -Value $null
	$sensorResult.prtg.text = $sensorMessage
}
$sensorResult | ConvertTo-Json -Depth 5 | Write-Output

In order to pass the url from the sensor's settings, enter it like this in the "Parameters" field: -Url "https://example.org/" -Timeout 10


Using %host in the parameters as a placeholder like this will also work: -Url "https://%host/" -Timeout 10


And if you're encountering issues with SSL (Such as the error "The request was aborted: Could not create SSL/TLS secure channel."), try adding TrustAllCerts to the parameters: -Url "https://%host/" -Timeout 10 -TrustAllCerts


The channel displaying the return code uses an already existing lookup (prtg.standardlookups.http.statuscode) to evaluate which codes are regarded as OK/Warning/Error. Feel free to create a custom lookup based on the existing one if you need.


Note: There's also another lookup called "prtg.standardlookups.http.statuscodedetailed" which contains definitions for every single return code, instead of ranges as in "prtg.standardlookups.http.statuscode".

Changelog:
  • 20/09/2023 - Version 2.5 adds the missing documentation for the TrustAllCerts parameter. Also adds support for TLS1.3 when TrustAllCerts is used.
  • 04/07/2022 - Version 2.4 changes the unit for the "Length" channel to Bytes so that the value can also be displayed in a more user-friendly format in PRTG. This only applies to newly created sensors and existing sensors may keep working but will still just display a number (without unit) as value.
  • 04/07/2022 - Version 2.3 makes the -TrustAllCerts also accept any Security Protocol, previously the script would behaved differently depending on different OS's and Powershell versions. Thanks to user Mihai for reporting this.
  • 17/03/2022 - Version 2.2 completely changes the code to a more modular approach which is easier to maintain. Functionally almost identical to 1.0
  • 09/03/2022 - Version 1.0 includes some bigger changes and is not backwards compatible (the parameters changed slightly). What's new: Invalid certificates are now only accepted when the switch-parameter TrustAllCerts is set. Otherwise you will see an SSL Error. Also fixed a small issue with the units from the ExecTime channel. Added better documentation and examples in the code itself
  • 01/09/2021 - Switched from Write-Host to Write-Output to conform with new "PowerShell Security Enhancement" (As of PRTG 21.2.68).
  • 25/06/2018 - Modified the try/catch to properly read the status code when it is part of an exception. When this happens, the Length is reported as -1.
  • 10/04/2018 - Added code to ignore SSL Certificate errors.
  • 28/07/2017 - Included a parameter for timeout. Default = 10 (seconds).


Disclaimer:
The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.