37

Similar to this question here I am trying to monitor if a set of website links are up and running or not responding. I have found the same PowerShell script over the Internet.

However, instead of direct website links I need to check more specific links, for example:

http://mypage.global/Chemical/ http://maypage2:9080/portal/site/hotpot/ 

When I am trying to check on the status of these links, I get the following output:

URL StatusCode StatusDescription ResponseLength TimeTaken http://mypage.global/Chemical/ 0 http://maypage2:9080/portal/site/hotpot/ 0 

The above links requires me to be connected to the VPN, but I can access these links from the browser.

Output of Invoke-WebRequest -Uri https://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url:

PS C:\Users\682126> Invoke-WebRequest -Uri https://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url The term 'Invoke-WebRequest' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:18 + Invoke-WebRequest <<<< -Uri https://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url > tmp.txt + CategoryInfo : ObjectNotFound: (Invoke-WebRequest:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException 

$PSVersionTable

Name Value ---- ----- CLRVersion 2.0.50727.5472 BuildVersion 6.1.7601.17514 PSVersion 2.0 WSManStackVersion 2.0 PSCompatibleVersions {1.0, 2.0} SerializationVersion 1.1.0.1 PSRemotingProtocolVersion 2.1 
4
  • 1
    What exactly is giving you that output? Commented Nov 28, 2013 at 6:37
  • 2
    What happens if you do this?: Invoke-WebRequest -Uri http://mypage.global/Chemical/ Commented Nov 28, 2013 at 6:56
  • 2
    Invoke-WebRequest is PowerShell 3 only. You will either have to upgrade to PowerShell 3 or find some other way of doing the request. Commented Nov 28, 2013 at 7:06
  • 1
    @Dangph upgrading is not a possibility as I donot hold admin rights... What other ways can this be achieved? Commented Nov 28, 2013 at 7:07

10 Answers 10

95

I recently set up a script that does this.

As David Brabant pointed out, you can use the System.Net.WebRequest class to do an HTTP request.

To check whether it is operational, you should use the following example code:

# First we create the request. $HTTP_Request = [System.Net.WebRequest]::Create('http://google.com') # We then get a response from the site. $HTTP_Response = $HTTP_Request.GetResponse() # We then get the HTTP code as an integer. $HTTP_Status = [int]$HTTP_Response.StatusCode If ($HTTP_Status -eq 200) { Write-Host "Site is OK!" } Else { Write-Host "The Site may be down, please check!" } # Finally, we clean up the http request by closing it. If ($HTTP_Response -ne $null) { $HTTP_Response.Close() } 
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, that did the job. But, when the URL is up if i were to display the response time for each URL, how am I to get that value?
To display the response time, you could wrap the part of your code that does the web request with (Measure-Command {HTTP REQUEST CODE HERE}).TotalSeconds
you can also set $HTTP_Request.Method="HEAD" this will give you just header part with no body, will be bit quicker as there is NO BODY being sent
Just checking: What should we be closing here on the last line, $HTTP_Response or $HTTP_Request?
$HTTP_Request, which is of type System.Net.HttpWebRequest, has no member close()
|
36

For people that have PowerShell 3 or later (i.e. Windows Server 2012+ or Windows Server 2008 R2 with the Windows Management Framework 4.0 update), you can do this one-liner instead of invoking System.Net.WebRequest:

$statusCode = wget http://stackoverflow.com/questions/20259251/ | % {$_.StatusCode} 

16 Comments

Probably worth highlighting that wget is an alias for Invoke-WebRequest (as is curl and iwr), I find that it is worth learning the native names in case you need to Google something.
To continue Ray's comment, I may as well also point out % is alias for ForEach-Object. Character $ designates a variable. _, when following a $, is an alias for $PSItem; which is an automatic variable (man about_Automatic_Variables) that contains the current object in the pipeline object. Which brings us to the "pipe" | (man about_Pipelines) and allows the output of the previous command to be used as input for the following command. So the full translation is $variable = Invoke-WebRequest http://stackoverflow.com/questions/20259251/ | ForEach-Object {$PSItem.StatusCode}
And finally, . is a shortcut way to retrieve the property (man about_Properties) of an object. So the actual full translation is $variable = Invoke-WebRequest $url | ForEach-Object {$PSItem | Select-Object -Property StatusCode}
This actually downloads the file which is very bad.
Also see this post: petri.com/testing-uris-urls-powershell It would suggest the following command: invoke-webrequest http://stackoverflow.com/questions/20259251/ -DisableKeepAlive -UseBasicParsing -Method head
|
27

You can try this:

function Get-UrlStatusCode([string] $Url) { try { (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive).StatusCode } catch [Net.WebException] { [int]$_.Exception.Response.StatusCode } } $statusCode = Get-UrlStatusCode 'httpstat.us/500' 

2 Comments

Adding -Method head worked better for me, it's faster and avoids downloading... (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive -Method head).StatusCode as used here https://www.petri.com/testing-uris-urls-powershell and on SO here
This helped me but note that it's broken in powershell 7 since the exception thrown is not the same as powershell 5, so specifying it meant the exception was not caught and would return 0. Removing the [Net.WebException] specification made it work on 5 and 7
10
$request = [System.Net.WebRequest]::Create('http://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url') $response = $request.GetResponse() $response.StatusCode $response.Close() 

2 Comments

in the above code, which parameter specifies that the link is operational or not?
Define "operational".
7

You must update the Windows PowerShell to minimum of version 4.0 for the script below to work.

 [array]$SiteLinks = "http://mypage.global/Chemical/test.html" "http://maypage2:9080/portal/site/hotpot/test.json" foreach($url in $SiteLinks) { try { Write-host "Verifying $url" -ForegroundColor Yellow $checkConnection = Invoke-WebRequest -Uri $url if ($checkConnection.StatusCode -eq 200) { Write-Host "Connection Verified!" -ForegroundColor Green } } catch [System.Net.WebException] { $exceptionMessage = $Error[0].Exception if ($exceptionMessage -match "503") { Write-Host "Server Unavaiable" -ForegroundColor Red } elseif ($exceptionMessage -match "404") { Write-Host "Page Not found" -ForegroundColor Red } } } 

Comments

6

Below is the PowerShell code that I use for basic web URL testing. It includes the ability to accept invalid certs and get detailed information about the results of checking the certificate.

$CertificateValidatorClass = @' using System; using System.Collections.Concurrent; using System.Net; using System.Security.Cryptography; using System.Text; namespace CertificateValidation { public class CertificateValidationResult { public string Subject { get; internal set; } public string Thumbprint { get; internal set; } public DateTime Expiration { get; internal set; } public DateTime ValidationTime { get; internal set; } public bool IsValid { get; internal set; } public bool Accepted { get; internal set; } public string Message { get; internal set; } public CertificateValidationResult() { ValidationTime = DateTime.UtcNow; } } public static class CertificateValidator { private static ConcurrentStack<CertificateValidationResult> certificateValidationResults = new ConcurrentStack<CertificateValidationResult>(); public static CertificateValidationResult[] CertificateValidationResults { get { return certificateValidationResults.ToArray(); } } public static CertificateValidationResult LastCertificateValidationResult { get { CertificateValidationResult lastCertificateValidationResult = null; certificateValidationResults.TryPeek(out lastCertificateValidationResult); return lastCertificateValidationResult; } } public static bool ServicePointManager_ServerCertificateValidationCallback(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { StringBuilder certificateValidationMessage = new StringBuilder(); bool allowCertificate = true; if (sslPolicyErrors != System.Net.Security.SslPolicyErrors.None) { if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch) == System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch) { certificateValidationMessage.AppendFormat("The remote certificate name does not match.\r\n", certificate.Subject); } if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) == System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) { certificateValidationMessage.AppendLine("The certificate chain has the following errors:"); foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus chainStatus in chain.ChainStatus) { certificateValidationMessage.AppendFormat("\t{0}", chainStatus.StatusInformation); if (chainStatus.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.Revoked) { allowCertificate = false; } } } if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable) == System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable) { certificateValidationMessage.AppendLine("The remote certificate was not available."); allowCertificate = false; } System.Console.WriteLine(); } else { certificateValidationMessage.AppendLine("The remote certificate is valid."); } CertificateValidationResult certificateValidationResult = new CertificateValidationResult { Subject = certificate.Subject, Thumbprint = certificate.GetCertHashString(), Expiration = DateTime.Parse(certificate.GetExpirationDateString()), IsValid = (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None), Accepted = allowCertificate, Message = certificateValidationMessage.ToString() }; certificateValidationResults.Push(certificateValidationResult); return allowCertificate; } public static void SetDebugCertificateValidation() { ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback; } public static void SetDefaultCertificateValidation() { ServicePointManager.ServerCertificateValidationCallback = null; } public static void ClearCertificateValidationResults() { certificateValidationResults.Clear(); } } } '@ function Set-CertificateValidationMode { <# .SYNOPSIS Sets the certificate validation mode. .DESCRIPTION Set the certificate validation mode to one of three modes with the following behaviors: Default -- Performs the .NET default validation of certificates. Certificates are not checked for revocation and will be rejected if invalid. CheckRevocationList -- Cerftificate Revocation Lists are checked and certificate will be rejected if revoked or invalid. Debug -- Certificate Revocation Lists are checked and revocation will result in rejection. Invalid certificates will be accepted. Certificate validation information is logged and can be retrieved from the certificate handler. .EXAMPLE Set-CertificateValidationMode Debug .PARAMETER Mode The mode for certificate validation. #> [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter()] [ValidateSet('Default', 'CheckRevocationList', 'Debug')] [string] $Mode ) begin { $isValidatorClassLoaded = (([System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GlobalAssemblyCache -eq $false }) | ?{ $_.DefinedTypes.FullName -contains 'CertificateValidation.CertificateValidator' }) -ne $null if ($isValidatorClassLoaded -eq $false) { Add-Type -TypeDefinition $CertificateValidatorClass } } process { switch ($Mode) { 'Debug' { [System.Net.ServicePointManager]::CheckCertificateRevocationList = $true [CertificateValidation.CertificateValidator]::SetDebugCertificateValidation() } 'CheckRevocationList' { [System.Net.ServicePointManager]::CheckCertificateRevocationList = $true [CertificateValidation.CertificateValidator]::SetDefaultCertificateValidation() } 'Default' { [System.Net.ServicePointManager]::CheckCertificateRevocationList = $false [CertificateValidation.CertificateValidator]::SetDefaultCertificateValidation() } } } } function Clear-CertificateValidationResults { <# .SYNOPSIS Clears the collection of certificate validation results. .DESCRIPTION Clears the collection of certificate validation results. .EXAMPLE Get-CertificateValidationResults #> [CmdletBinding(SupportsShouldProcess = $false)] param() begin { $isValidatorClassLoaded = (([System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GlobalAssemblyCache -eq $false }) | ?{ $_.DefinedTypes.FullName -contains 'CertificateValidation.CertificateValidator' }) -ne $null if ($isValidatorClassLoaded -eq $false) { Add-Type -TypeDefinition $CertificateValidatorClass } } process { [CertificateValidation.CertificateValidator]::ClearCertificateValidationResults() Sleep -Milliseconds 20 } } function Get-CertificateValidationResults { <# .SYNOPSIS Gets the certificate validation results for all operations performed in the PowerShell session since the Debug cerificate validation mode was enabled. .DESCRIPTION Gets the certificate validation results for all operations performed in the PowerShell session since the Debug certificate validation mode was enabled in reverse chronological order. .EXAMPLE Get-CertificateValidationResults #> [CmdletBinding(SupportsShouldProcess = $false)] param() begin { $isValidatorClassLoaded = (([System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GlobalAssemblyCache -eq $false }) | ?{ $_.DefinedTypes.FullName -contains 'CertificateValidation.CertificateValidator' }) -ne $null if ($isValidatorClassLoaded -eq $false) { Add-Type -TypeDefinition $CertificateValidatorClass } } process { return [CertificateValidation.CertificateValidator]::CertificateValidationResults } } function Test-WebUrl { <# .SYNOPSIS Tests and reports information about the provided web URL. .DESCRIPTION Tests a web URL and reports the time taken to get and process the request and response, the HTTP status, and the error message if an error occurred. .EXAMPLE Test-WebUrl 'http://websitetotest.com/' .EXAMPLE 'https://websitetotest.com/' | Test-WebUrl .PARAMETER HostName The Hostname to add to the back connection hostnames list. .PARAMETER UseDefaultCredentials If present the default Windows credential will be used to attempt to authenticate to the URL; otherwise, no credentials will be presented. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [Uri] $Url, [Parameter()] [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = 'Get', [Parameter()] [switch] $UseDefaultCredentials ) process { [bool] $succeeded = $false [string] $statusCode = $null [string] $statusDescription = $null [string] $message = $null [int] $bytesReceived = 0 [Timespan] $timeTaken = [Timespan]::Zero $timeTaken = Measure-Command ` { try { [Microsoft.PowerShell.Commands.HtmlWebResponseObject] $response = Invoke-WebRequest -UseDefaultCredentials:$UseDefaultCredentials -Method $Method -Uri $Url $succeeded = $true $statusCode = $response.StatusCode.ToString('D') $statusDescription = $response.StatusDescription $bytesReceived = $response.RawContent.Length Write-Verbose "$($Url.ToString()): $($statusCode) $($statusDescription) $($message)" } catch [System.Net.WebException] { $message = $Error[0].Exception.Message [System.Net.HttpWebResponse] $exceptionResponse = $Error[0].Exception.GetBaseException().Response if ($exceptionResponse -ne $null) { $statusCode = $exceptionResponse.StatusCode.ToString('D') $statusDescription = $exceptionResponse.StatusDescription $bytesReceived = $exceptionResponse.ContentLength if ($statusCode -in '401', '403', '404') { $succeeded = $true } } else { Write-Warning "$($Url.ToString()): $($message)" } } } return [PSCustomObject] @{ Url = $Url; Succeeded = $succeeded; BytesReceived = $bytesReceived; TimeTaken = $timeTaken.TotalMilliseconds; StatusCode = $statusCode; StatusDescription = $statusDescription; Message = $message; } } } Set-CertificateValidationMode Debug Clear-CertificateValidationResults Write-Host 'Testing web sites:' 'https://expired.badssl.com/', 'https://wrong.host.badssl.com/', 'https://self-signed.badssl.com/', 'https://untrusted-root.badssl.com/', 'https://revoked.badssl.com/', 'https://pinning-test.badssl.com/', 'https://sha1-intermediate.badssl.com/' | Test-WebUrl | ft -AutoSize Write-Host 'Certificate validation results (most recent first):' Get-CertificateValidationResults | ft -AutoSize 

1 Comment

This is an interesting solution but it seems your try/catch on line 276 is not working for me in PoSH 5 or 7.4.6 so I'm guessing this was written with an older version in mind. Using -erroraction stop isn't sufficient but there's an interesting discussion over here that may help: stackoverflow.com/a/76392625/5419381. I just haven't found exactly the right way to integrate it in your script yet
3

For powershell (7) core, this works:

curl -I gourav.io 

Output:

HTTP/1.1 308 Permanent Redirect Date: Tue, 13 Apr 2021 20:29:43 GMT Content-Type: text/plain Connection: keep-alive Location: https://gourav.io/ Refresh: 0;url=https://gourav.io/ server: Vercel x-vercel-id: bom1::zfh9m-1618345783130-62d01e38e332 

OR

Invoke-WebRequest https://gourav.io 

Output:

StatusCode : 200 StatusDescription : OK Content : <!DOCTYPE html><html lang="en-US"><head><script async="" src="https://www.googletagmanager.com/gtag/js?id=G-JF3BSQ1LL2"></script><script> window.dataLayer = window.dataLayer || []; … RawContent : HTTP/1.1 200 OK ... ... 

1 Comment

Note that the first one works in PowerShell 5.1 as well so long as you call curl.exe or remove the 'curl' alias.
1

I use this and works, (Returns "Ok" if link is available) but it shows the red letters of the error if link is not working. How can I remove the error reporting on this snippet?

$DownloadLink = "https://www.tightvnc.com/download/2.8.59/tightvnc-2.8.59-gpl-setup-bit.msi" 

$NetAvailable = (Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -DisableKeepAlive -Method Head).StatusDescription

$NetAvailable = OK

 If ($NetAvailable -eq "OK") {Write-Host "Attempting Download";wget -O "$Destination\$FileName" "$DownloadLink"} Else {"";Write-Warning "Could NOT Download, Manually Copy $ProgramName to $Destination BEFORE Proceeding!";"";PAUSE} 

But if link is not working will give me an error and then move to the "Else" It works, I would just like to get rid of the error letters.

1 Comment

If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From Review
1

this is a way to use cmd.exe to do the same/similar:

if you install curl for windows https://curl.se/windows/ you can do a one liner like this:

FOR /F %i IN (myurls.txt) DO (echo %i && c:\curl\bin\curl.exe -I %i | findstr HTTP) >> output.txt

this will echo the url used and write the HTTP response below it.

note: output.txt would need to exist but be empty and be in the same folder you run the command. change the curl.exe path to match where it installs, if not put in the environment path

Comments

1

**

$statusCode ="0" # I am assigning the statuscode as 0. if website is running then next step will change it it 200 if website is not running then it will be 0 only $statusCode = wget http://yourwebsite.com -UseBasicParsing | % {$_.StatusCode} If ($statusCode -eq 200) { # run your script here ($NewResult = "1") } else { # run your script here ($NewResult = "0") } 

**

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.