Microsoft Teams Tenant Wide CSV Report

Sam Cosby

Hello World!  (10/29) - I've updated the Teams CSV Report to be compliant with Teams PowerShell 0.9.5. Please run as a Global Admin, or you may not get all the detailed information below. The script pulls all of the following information for all Teams in your organization:


  • Team Name
  • Team GUID
  • Team Owners
  • Team Access Type
  • Team User Count
  • Team SharePoint Site
  • Team Guests
NOTE: You must be signed into the Teams PowerShell Module & Exchange Online PowerShell Module for the script below to work. Additionally, it can take a while to run if you have many Teams & Groups in your organization!
## Created by SAMCOS @ MSFT, Collaboration with others!
## You must first connect to Microsoft Teams Powershell & Exchange Online Powershell for this to work.
## Links:
## Teams: https://www.powershellgallery.com/packages/MicrosoftTeams/0.9.5
## Exchange: https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/connect-to-exchange-online-powershell?view=exchange-ps
## Have fun! Let me know if you have any comments or asks! 

$AllTeamsInOrg = (Get-Team).GroupID
$TeamList = @()

Write-Output "This may take a little bit of time... Please sit back, relax and enjoy some GIFs inside of Teams!"
Write-Host ""

Foreach ($Team in $AllTeamsInOrg)
        $TeamGUID = $Team.ToString()
        $TeamGroup = Get-UnifiedGroup -identity $Team.ToString()
        $TeamName = (Get-Team | ?{$_.GroupID -eq $Team}).DisplayName
        $TeamOwner = (Get-TeamUser -GroupId $Team | ?{$_.Role -eq 'Owner'}).User
        $TeamUserCount = ((Get-TeamUser -GroupId $Team).UserID).Count
        $TeamGuest = (Get-UnifiedGroupLinks -LinkType Members -identity $Team | ?{$_.Name -match "#EXT#"}).Name
            if ($TeamGuest -eq $null)
                $TeamGuest = "No Guests in Team"
        $TeamList = $TeamList + [PSCustomObject]@{TeamName = $TeamName; TeamObjectID = $TeamGUID; TeamOwners = $TeamOwner -join ', '; TeamMemberCount = $TeamUserCount; TeamSite = $TeamGroup.SharePointSiteURL; AccessType = $TeamGroup.AccessType; TeamGuests = $TeamGuest -join ','}


$TestPath = test-path -path 'c:\temp'
if ($TestPath -ne $true) {New-Item -ItemType directory -Path 'c:\temp' | Out-Null
    write-Host  'Creating directory to write file to c:\temp. Your file is uploaded as TeamsDatav2.csv'}
else {Write-Host "Your file has been uploaded to c:\temp as 'TeamsDatav2.csv'"}
$TeamList | export-csv c:\temp\TeamsDatav2.csv -NoTypeInformation



10 Replies
Nice one...could you also share your script in the PowerShell Gallery so others can download it from there?
Much appreciated, thanks for the post. Will try this out!!

Hi Sam,
i sent you a message to your inbox about the script. Just a couple of short questions, would apreciate if you have time answering.




Thank you very much for a great script.


I found one thing.

An error happens when "$teamschannels = Get-TeamChannel" is executed. So the next line "$o365GroupMemberList = (Get-UnifiedGroupLinks ... " might not be executed for '403' and '404' case. 

I thihk member addresess could be collected before calling Get-TeamChannel so that the member list is set even if 404 or 404 happens.




This is not working as expected. The output for Members and Owners starts off blank then repeats at times and is almost completely inaccurate. The Creators data is null as well. 


For example, the CSV shows the first 17 groups as having no members even though the member count ranges from 1-30. The 18th group appears to be correct but groups 19-24 show the exact same member list as 18 even though they are completely different.

I have added Import-PSSession and Connect-MicrosoftTeams plus modified to show Display Name instead of SMTP but have tried it modified and unmodified with the same results. 


Please advise. 

EDIT: Doesn't seem to work reliably... 


I started out with using the Exchange PowerShell module Get-UnifiedGroup, but because we have such a tight network security practice, it was hard to get it working on normal machines behind a proxy.


So I write a similar script using AzureAD and MicrosoftTeams module which can be proxied because it uses the Microsoft Graph API from Microsoft (HTTP Rest) instead of the WinRM Exchange module.


I don't have a big tenant, so if anybody can test performance, let me know.


Gist: https://gist.github.com/glego/5b122deece0c5fcfe464d69eb21ab450


Get all Microsoft Teams Groups
This script will check any existing AzureAD Group, if there are any Teams Users
attached to it. If so it will create a custom object and mark it with an isTeams flag.

Import-Module AzureAD
Import-Module MicrosoftTeams


# Get Potential Team Groups
$AzureADGroups = Get-AzureADGroup | Where-Object {$_.ObjectType -eq "Group" -and $_.MailEnabled -eq $true}


foreach ($Group in $AzureADGroups) {

# Get the Object Id for each Group
$GroupId = $Group.ObjectId

# Create Team HashTable to Store Retrieved Information
$Team = [ordered]@{}
$Team.Add("GroupId", $GroupId)
$Team.Add("DisplayName", $Group.DisplayName)
$Team.Add("Description", $Group.Description)
$Team.Add("Mail", $Group.Mail)
$Team.Add("MailNickname", $Group.MailNickname)

# Get Team Users
$TeamUser = Get-TeamUser -GroupId $GroupId

if ($TeamUser) {

# Teams Users Exists!
$Team.Add("isTeams", $true)
$Team.Add("TeamUsers", $TeamUser)

} else {
# No Teams Users...
$Team.Add("isTeams", $false)

# (Optional) Add the Group Information to the HashTable
$Team.Add("Group", $Group)

# Dirty way to convert the HashTable into a PSObject
## Note: Somehow New-Object PSCustomObject -Property $Team is not working ¯\_(ツ)_/¯
$TeamJSON = ConvertTo-Json -InputObject $Team
$TeamObject = $TeamJSON | ConvertFrom-Json

# Add the Object to the Teams Collection
$Teams += $TeamObject

Write-Output $Teams


Glenn, this also does not appear to be accurate. We use a [Team] suffix when we create new Teams and I know of at least 30 in our tenant but this script only captured one.

MIcrosoft is so incredibly frustrating when they do not think through the customer experience.

It looks like someone figured out how to produce a basic list using MS Graph API. Check this out:



This looks ideal.
Anyway to produce a list of team names, descriptions, and the deep url so that colleagues can identify interesting groups and ask to join.
So annoying that Teams does not have this capability.

Related Conversations
Teams Crashes on Startup
Slarti in Microsoft Teams on
45 Replies
Teams for Mac Client
tlindgren in Microsoft Teams on
5 Replies
Teams Calling - Dial pad missing
Chris Cooper in Microsoft Teams on
34 Replies