To list guest users in Microsoft Entra ID, read every account whose user type is Guest, with its invitation state and last successful sign-in. The sign-in date needs Microsoft Entra ID P1 or P2, and only guests invited through the invitation API carry an invitation state. A person whose user type is Member is not listed.
| Method | Best fit |
|---|---|
| PowerShell | A CSV of every guest with its invitation state and last sign-in, each flagged with a status. |
| Admin centre | A quick look: filter the Users list on user type and add a last sign-in column. |
| Altivane | Recommended for recurring guest reviews, with stale and pending guests rated against a threshold. |
Before you start
Use an account that can read sign-in activity: Reports Reader is the least privileged role Microsoft lists. The tenant needs Microsoft Entra ID P1 or P2 for the sign-in dates. The PowerShell example requests User. and AuditLog.; your organisation may require administrator consent.
A guest is an account whose user type is Guest, usually a person invited from another organisation. A sign-in date can take up to 24 hours to update, and a guest who last signed in before April 2020 has none. The examples read and export every guest and change nothing.
Option 1
List guest users with PowerShell
Install the modules once, then connect and export every guest with a status. The filter runs in Microsoft Graph, so only guests come back. Change $days to set when a guest counts as inactive.
# Install once, if the modules are not already installed.
Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Users -Scope CurrentUser$ErrorActionPreference = 'Stop'
$days = 90
$cutoff = (Get-Date).ToUniversalTime().AddDays(-$days)
Connect-MgGraph -Scopes 'User.Read.All', 'AuditLog.Read.All' -NoWelcome
try {
$properties = 'displayName,mail,userPrincipalName,accountEnabled,createdDateTime,' +
'externalUserState,externalUserStateChangeDateTime,signInActivity'
$guests = Get-MgUser -All -Filter "userType eq 'Guest'" -Property $properties
$report = @(foreach ($guest in $guests) {
$last = $guest.SignInActivity.LastSuccessfulSignInDateTime
$status = if (-not $guest.AccountEnabled) { 'Disabled' }
elseif ($guest.ExternalUserState -eq 'PendingAcceptance') { 'Invitation pending' }
elseif (-not $last) { 'Never signed in' }
elseif ($last.ToUniversalTime() -le $cutoff) { "Inactive $days+ days" }
else { 'Active' }
[pscustomobject]@{
DisplayName = $guest.DisplayName
Email = $guest.Mail
Status = $status
LastSuccessfulSignIn = $last
Created = $guest.CreatedDateTime
InvitationState = $guest.ExternalUserState
InvitationChanged = $guest.ExternalUserStateChangeDateTime
}
})
if ($report.Count -eq 0) {
Write-Output 'There are no guest accounts in the tenant.'
} else {
$report | Sort-Object Status, LastSuccessfulSignIn |
Export-Csv -Path './guest-users.csv' -NoTypeInformation -Encoding utf8
$pending = @($report | Where-Object Status -eq 'Invitation pending').Count
Write-Output "$($report.Count) guest accounts, $pending with the invitation not accepted."
}
} finally {
Disconnect-MgGraph | Out-Null
}The status is the first rule that fits, in the order shown. Never signed in means no sign-in date on record, so read Created beside it before acting on a new guest. To keep only the guests that need a look, filter on Status before exporting.
Check a single guest
Reconnect, then read 1 guest's invitation. Search on the mail address: a guest's user principal name carries #EXT#.
# Run while connected to Microsoft Graph. Replace the example address.
$filter = "mail eq 'person@example.com'"
$properties = 'displayName,externalUserState,externalUserStateChangeDateTime,createdDateTime'
Get-MgUser -Filter $filter -Property $properties |
Select-Object DisplayName, ExternalUserState, ExternalUserStateChangeDateTime, CreatedDateTimeOption 2
List guest users in the admin centre
- Sign in to the Microsoft Entra admin centre as at least a Reports Reader.
- Go to Entra ID > Users > All users.
- Select Add filter, choose User type and select Guest.
- Select Manage view, then Edit columns. Select + Add column, choose Last interactive sign-in time and select Save.
- To read 1 guest's invitation, open them: the profile shows Invitation state, Pending acceptance until they accept.
- To keep the list, select Download users, then Start. The file holds the filtered list.
This suits a quick look at 1 tenant. The column counts interactive sign-ins only, and nothing here flags stale guests, so you compare the dates yourself.
Option 3 ยท Recommended for recurring guest reviews
Review guest users with Altivane
- Open Altivane and choose the tenant.
- Build the tenant's documents with the Identity scorecard report in full, so accounts are listed as well as counted, and set Stale users and New account grace in days.
- Open the tenant's Excel workbook and find Guest Users Needing Review; Guest Users lists every guest.
- Read User Account Summary for guest counts and the scorecard for how the review list rates against your thresholds.
Altivane reads the same sign-in activity, so the same licence applies; where it cannot be read, the review list says Not collected and Guest Users still lists every guest. The review list holds enabled guests that are stale, never signed in or have not accepted their invitation. Stale users starts at 180 days. The scorecard marks the list Warning or Critical at the share of enabled guests you set, 25% and 50% to start. The build also writes the tenant's Word report.
Contact usCommon questions
Why is a guest I invited yesterday on the list?
An invitation not accepted is a finding in itself, so a pending guest is listed whatever its age. A guest added without the invitation API has no invitation state and is judged on sign-ins alone.
Why is a person from a partner organisation missing?
An administrator can change a user type between Member and Guest, and an external person with member-level access is a Member, so is not listed here. For members who have gone quiet, see how to find inactive users.
Is there a built-in report for inactive guests?
Yes, with Microsoft Entra ID Governance or the Entra Suite. Go to ID Governance > Dashboard and, on the Guest access governance card, select View inactive guests. It uses 90 days by default.
Microsoft references
Technical references checked on 5 October 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.