Microsoft Entra ID security

How to list guest users in Microsoft Entra ID

List guest accounts with Microsoft Graph PowerShell, filter the Users list in the Entra admin centre, or use Altivane's Identity report for guests that are stale or never accepted their invitation.

By the Published Updated

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.

Choose the method that fits the job
MethodBest fit
PowerShellA CSV of every guest with its invitation state and last sign-in, each flagged with a status.
Admin centreA quick look: filter the Users list on user type and add a last sign-in column.
AltivaneRecommended 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.Read.All and AuditLog.Read.All; 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.

PowerShell
# Install once, if the modules are not already installed.
Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Users -Scope CurrentUser
PowerShell
$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#.

PowerShell
# 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, CreatedDateTime

Option 2

List guest users in the admin centre

  1. Sign in to the Microsoft Entra admin centre as at least a Reports Reader.
  2. Go to Entra ID > Users > All users.
  3. Select Add filter, choose User type and select Guest.
  4. Select Manage view, then Edit columns. Select + Add column, choose Last interactive sign-in time and select Save.
  5. To read 1 guest's invitation, open them: the profile shows Invitation state, Pending acceptance until they accept.
  6. 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.

Common 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.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us