Powershell
Invoke-WebRequest
HTTPS error
Powershell v3
Troubleshooting

Powershell v3 Invoke-WebRequest HTTPS error

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

PowerShell's Invoke-WebRequest often fails with HTTPS errors when connecting to endpoints that use self-signed certificates, outdated TLS protocols, or certificate chains that the system does not trust. The most common error is The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. The fix depends on whether the issue is the TLS protocol version, the certificate trust chain, or certificate validation itself.

Fix 1: Set TLS 1.2 (Most Common Fix)

PowerShell 3-5 defaults to TLS 1.0/1.1, which most modern servers reject. Force TLS 1.2 before making the request.

powershell
1[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
2
3$response = Invoke-WebRequest -Uri "https://api.example.com/data"
4$response.StatusCode

For maximum compatibility, enable multiple TLS versions:

powershell
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13

In PowerShell 7+, TLS 1.2 is the default, so this fix is only needed for Windows PowerShell 5.1 and earlier.

Fix 2: Bypass Certificate Validation (Development Only)

For development environments with self-signed certificates, you can bypass certificate validation entirely. Never use this in production.

powershell
1# PowerShell 5.1 and earlier
2add-type @"
3using System.Net;
4using System.Security.Cryptography.X509Certificates;
5public class TrustAllCertsPolicy : ICertificatePolicy {
6    public bool CheckValidationResult(
7        ServicePoint srvPoint, X509Certificate certificate,
8        WebRequest request, int certificateProblem) {
9        return true;
10    }
11}
12"@
13[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
14
15Invoke-WebRequest -Uri "https://self-signed.example.com"
powershell
# PowerShell 7+ has a built-in parameter
Invoke-WebRequest -Uri "https://self-signed.example.com" -SkipCertificateCheck

Fix 3: Install the Certificate

The proper fix for self-signed or internal CA certificates is to install them in the trusted root certificate store.

powershell
1# Export the certificate from the server
2$cert = [System.Net.ServicePointManager]::ServerCertificateValidationCallback
3
4# Import a .cer file into the trusted root store
5Import-Certificate -FilePath "C:\certs\internal-ca.cer" -CertStoreLocation Cert:\LocalMachine\Root

Or use certutil:

cmd
certutil -addstore Root C:\certs\internal-ca.cer

After importing, Invoke-WebRequest trusts the server without any code-level workarounds.

Fix 4: Use Invoke-RestMethod for API Calls

Invoke-RestMethod automatically parses JSON responses and has the same TLS behavior. If you are calling REST APIs, it is often more convenient.

powershell
1[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
2
3$data = Invoke-RestMethod -Uri "https://api.example.com/users" -Method Get
4$data | ForEach-Object { Write-Output $_.name }

Diagnosing the Exact Error

Check which TLS protocols the server supports and what your PowerShell session is using.

powershell
1# Check current TLS setting
2[Net.ServicePointManager]::SecurityProtocol
3
4# Test server connectivity with detailed error
5try {
6    $response = Invoke-WebRequest -Uri "https://api.example.com" -ErrorAction Stop
7    Write-Output "Success: $($response.StatusCode)"
8} catch {
9    Write-Output "Error: $($_.Exception.Message)"
10    if ($_.Exception.InnerException) {
11        Write-Output "Inner: $($_.Exception.InnerException.Message)"
12    }
13}

The inner exception message usually reveals whether the issue is TLS protocol mismatch, certificate trust failure, or something else.

Common Pitfalls

  • Bypassing certificate validation in production scripts — this disables all TLS security and exposes the connection to man-in-the-middle attacks.
  • Setting the TLS protocol inside a function but not at script scope — ServicePointManager settings apply process-wide but must be set before the first HTTPS connection.
  • Forgetting that PowerShell 7 uses a different HTTP stack (HttpClient) than Windows PowerShell 5.1 (WebRequest) — the -SkipCertificateCheck parameter only exists in PowerShell 7+.
  • Not checking if a proxy server is intercepting HTTPS traffic — corporate proxies often inject their own certificates, requiring the proxy CA to be trusted.
  • Assuming TLS 1.3 is available on older Windows versions — TLS 1.3 requires Windows 10 version 1903 or later.

Summary

  • Set [Net.ServicePointManager]::SecurityProtocol to TLS 1.2 for PowerShell 5.1 and earlier.
  • Use -SkipCertificateCheck in PowerShell 7+ for development with self-signed certificates.
  • Install internal CA certificates in the trusted root store for the proper production fix.
  • Check the inner exception message to diagnose whether the issue is TLS version, certificate trust, or proxy interference.
  • Never bypass certificate validation in production environments.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.