When you are in an environment with strict internet access, you need to figure out which Microsoft services to open to which destination for services like Exchange Online, Teams, Endpoint Manager, and so on. Microsoft publishes this on its website, but in this blog post, I would like to show you a convenient way to output that information to an Out-GridView or a CSV file.
How the script works
It downloads the information from a Microsoft-hosted link that contains all IP addresses and FQDNs with their TCP or UDP ports, then converts the JSON to an object. Afterward, it displays the information in an Out-GridView Window for easy sorting and filtering (you can copy your selection in the window with CTRL-C), or exports to a CSV if you use the CSVPath parameter.
Running the script
When running it without any parameters, it looks like this:

When running it with the -CSVPath parameter and specifying the output path, like in the example below, which saves it to d:\temp\endpoint.csv, it looks like this:
Get-MicrosoftEndpoints -CSVPath d:\temp\endpoints.csv

The script
Below is the script. You can add it to your PowerShell profile by:
notepad $profile add '. c:\scripts\get-microsoftendpoints.ps1' quit/save and start a new PowerShell session
function Get-MicrosoftEndpoints {
param (
[parameter(parameterSetName = "CSV")][string]$CSVPath
)
#Hide download progress, get current JSON url, retrieve all Endpoints and Convert it from JSON format
$ProgressPreference = "SilentlyContinue"
try {
$site = Invoke-WebRequest -Uri 'https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide' -UseBasicParsing
$jsonlink = ($site.Links | where-Object OuterHTML -match 'JSON formatted').href
}
catch {
Write-Warning ("Error downloading JSON file, please check if https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide is accessible")
return
}
try {
$Endpoints = Invoke-WebRequest -Uri $jsonlink -ErrorAction Stop -UseBasicParsing | ConvertFrom-Json
Write-Host ("Downloading worldwide Microsoft Endpoints") -ForegroundColor Green
}
catch {
Write-Warning ("Error downloading worldwide Microsoft Endpoints, please check if $($jsonlink) is accessible")
return
}
Write-Host ("Processing items...") -ForegroundColor Green
$Total = foreach ($Endpoint in $Endpoints) {
#Check if IPs are available for the Endpoint, set to not available if not
if (-not $Endpoint.ips) {
$IPaddresses = 'Not available'
}
else {
$IPaddresses = $Endpoint.ips.split(' ') -join ', '
}
#Check if TCP ports are available for the Endpoint, set to not available if not
if (-not $Endpoint.tcpPorts) {
$TCPPorts = 'Not available'
}
else {
$TCPPorts = $Endpoint.TCPPorts.split(',') -join ', '
}
#Check if UDP ports are available for the Endpoint, set to not available if not
if (-not $Endpoint.udpPorts) {
$UDPPorts = 'Not available'
}
else {
$UDPPorts = $Endpoint.udpPorts.split(',') -join ', '
}
#Check if there are notes for the Endpoint, set to not available if not
if (-not $Endpoint.notes) {
$Notes = 'Not available'
}
else {
$Notes = $Endpoint.Notes
}
#Check if URLs are available for the Endpoint, set to not available if not
if (-not $Endpoint.urls) {
$URLlist = 'Not available'
}
else {
$URLlist = $Endpoint.urls -join ', '
}
[PSCustomObject]@{
serviceArea = $Endpoint.serviceArea
serviceAreaDisplayName = $Endpoint.serviceAreaDisplayName
urls = $URLlist
ips = $IPaddresses
tcpPorts = $TCPPorts
udpPorts = $UDPPorts
notes = $notes
expressRoute = $Endpoint.expressRoute
category = $Endpoint.Category
required = $Endpoint.required
}
}
#Export data to specified $CSVPath if specified
if ($CSVPath) {
try {
New-Item -Path $CSVPath -ItemType File -Force:$true -ErrorAction Stop | Out-Null
$Total | Sort-Object serviceAreaDisplayName | Export-Csv -Path $CSVPath -Encoding UTF8 -Delimiter ';' -NoTypeInformation
Write-Host ("Saved results to {0} `nDone!" -f $CSVPath) -ForegroundColor Green
}
catch {
Write-Warning ("Could not save results to {0}" -f $CSVPath)
}
}
else {
#Export to Out-Gridview
Write-Host ("Exporting results to Out-GridView `nDone!") -ForegroundColor Green
$Total | Sort-Object serviceAreaDisplayName | Out-GridView -Title 'Microsoft Endpoints Worldwide'
}
}
Download the script(s) from GitHub here
You should include UUID generation in your script as it mentions on the page here: https://learn.microsoft.com/en-us/microsoft-365/enterprise/microsoft-365-ip-web-service?view=o365-worldwide. The UUID used in your example may become unusable in the future, which will break all the script for all the people who’re using it!
Yep, you’re right and I did mention it too in the post 😊 I’ve did a blog earlier in which I retrieved the current link, will update this one later with the same method
I changed the script so that it checks for the current JSON link, this makes it more dynamic in case the download link changes on the page.
you have a typo on the suggestion for the profile edit. “add ‘. c:\scripts\get-microsoftendpoints.csv’” should presumably be add ‘. c:\scripts\get-microsoftendpoints.ps1’
You’re right! Thanks, updated it now 😅