← All posts
GuidesOctober 28, 2026 · 7 min read

How to find inactive users in Microsoft 365

An inactive user is an account that is still enabled and still licensed, but that nobody has signed in with for months. Each one is a paid seat doing nothing. Microsoft gives you three places to look: the usage reports in the Microsoft 365 admin center, the user list in the Microsoft Entra admin center, and the signInActivity data in Microsoft Graph. They do not measure the same thing, and the difference decides whether you remove a license from someone who left in the spring or from someone who reads email on their phone every day. This guide covers all three, the license and permissions each one needs, and which date to trust.

Need the list today?

Sentsai’s free, read-only scan reads the same sign-in data and flags licensed accounts with no sign-in for 180 days or more, E3 and E5 seats idle for 30 to 179 days, and accounts that never signed in. The free scan shows the savings total; the itemized report is paid.

Start your free scanSee a sample report

Needs a one-time approval of read-only access from an administrator who can approve apps. Not an admin? Email this to yours.

First, decide what inactive means

Microsoft does not ship an inactive-user report. Its guidance on inactive accounts says to work from the last sign-in date, and notes that many organizations settle on a window between 90 and 180 days. Pick your window before you pull any data, and list the legitimate reasons someone might not sign in: parental leave, sabbaticals, seasonal staff, long-term sick leave. Then judge each account on the last time it actually signed in, not the last time someone tried to.

Option 1: usage reports in the Microsoft 365 admin center

In the Microsoft 365 admin center, go to Reports, then Usage, select Microsoft 365 apps, and open the Active users tab. The table lists each user with a last active date for Exchange, OneDrive, SharePoint, Viva Engage and Teams, and the date each of those licenses was assigned. Choose the 7, 30, 90 or 180 day view and select Export to download the whole table as a CSV file. The Reports Reader role is enough to open it.

  • The data usually runs 24 to 48 hours behind, which is fine for a 90-day review.
  • By default the report shows identifiers instead of names. A Global Administrator can change that under Settings, Org settings, Services, Reports by clearing Conceal user, group, and site names in all reports.
  • It only sees those five services. Someone who works all day in a line-of-business app that signs in through Microsoft Entra ID looks idle here and is not. Treat the report as activity per service, not as proof that an account is abandoned.
  • The longest window is 180 days, so it cannot tell you who has been gone for a year.

Option 2: last sign-in in the Microsoft Entra admin center

Sign in to the Microsoft Entra admin center as at least a Reports Reader and browse to Entra ID, then Users. Select Manage view, then Edit columns, add the Last interactive sign-in time column, and save. Add a filter on that column with the less than or equal operator and your cutoff date, and you have everyone whose last interactive sign-in is older than the window. For a single user, the Sign-ins tile on the user overview shows recent activity, although Microsoft notes it can take up to 24 hours to update.

Two limits apply. The column counts interactive sign-ins only, so people who mostly authenticate through mobile apps and background token refreshes can look older than they are. And the sign-in logs behind See all sign-ins are short: Microsoft Entra keeps them for seven days on the free tier and 30 days with Microsoft Entra ID P1 or P2. They are good for investigating one account, but they cannot show six months of absence. The timestamps in the next section can, because Microsoft keeps them on the user object for as long as the account exists.

Option 3: Microsoft Graph PowerShell

For a tenant-wide list you can filter, sort and keep, read the signInActivity property of every user through Microsoft Graph. It carries three timestamps, and picking the right one is most of the job:

  • lastSignInDateTime: the last interactive sign-in attempt, successful or not. Failed attempts count, so a password-spray attempt against a dormant account makes it look recently used. Microsoft itself warns that this value might not reflect actual use.
  • lastNonInteractiveSignInDateTime: the last time a client signed in on the user’s behalf, such as Outlook or Teams on a phone refreshing a token. People who live in those apps can go weeks without an interactive sign-in.
  • lastSuccessfulSignInDateTime: the most recent successful sign-in, interactive or non-interactive. This is the one Microsoft recommends for inactive-user reports. It has been recorded since December 1, 2023 and was not backfilled, so an empty value means no successful sign-in since then, or none ever.

Prerequisites: the tenant needs Microsoft Entra ID P1 or P2 (Microsoft 365 E3 includes P1, and Microsoft 365 E5 includes P1 and P2), because Microsoft only releases signInActivity to premium tenants. The session needs the AuditLog.Read.All and User.Read.All permissions, and the account you run it as needs a role that can read sign-in activity, of which Reports Reader is the least privileged. Use the Microsoft Graph PowerShell SDK: the MSOnline module was retired in May 2025 and the AzureAD module is deprecated, so old scripts built on Get-MsolUser are not an option.

Step 1: connect

Connect-MgGraph -Scopes "User.Read.All", "AuditLog.Read.All"

Step 2: read every user with sign-in activity

$users = Get-MgUser -All -Property Id, DisplayName, UserPrincipalName, AccountEnabled, CreatedDateTime, AssignedLicenses, SignInActivity

Step 3: enabled, licensed, no successful sign-in in 90 days

$cutoff = (Get-Date).AddDays(-90); $users | Where-Object { $_.AccountEnabled -and $_.AssignedLicenses.Count -gt 0 -and (-not $_.SignInActivity.LastSuccessfulSignInDateTime -or $_.SignInActivity.LastSuccessfulSignInDateTime -lt $cutoff) } | Select-Object DisplayName, UserPrincipalName, CreatedDateTime, @{n="LastSuccessful"; e={$_.SignInActivity.LastSuccessfulSignInDateTime}}, @{n="LastNonInteractive"; e={$_.SignInActivity.LastNonInteractiveSignInDateTime}} | Export-Csv .\inactive-licensed-users.csv -NoTypeInformation

Prefer raw Graph calls? The same data comes from the users endpoint, and you can filter on the timestamp directly. Microsoft documents two catches: a signInActivity filter cannot be combined with any other filterable property, so you cannot also filter on accountEnabled in the same request, and pages are capped at 500 users when you select or filter on signInActivity. Accounts that never signed in have no timestamp and will not match a date filter, so look for them separately.

Microsoft Graph request

GET https://graph.microsoft.com/v1.0/users?$filter=signInActivity/lastSuccessfulSignInDateTime le 2026-07-30T00:00:00Z

Before you remove anything

  • Look at lastNonInteractiveSignInDateTime as well. If it is recent, a device or app is still signing in as that person, which means either they are still working or someone else is using the account. Both are worth knowing before the license goes.
  • Check CreatedDateTime. An account created last week with no sign-in is onboarding, not waste.
  • Leave out service accounts, emergency access accounts and anyone on documented leave, and send the rest to their managers to confirm.
  • Removing a license starts a 30-day clock on the user’s Exchange Online data. After that it is deleted, apart from content kept by retention policies or labels, so settle retention first.
  • Removing the license frees the seat for the next hire. It does not reduce what you pay until the subscription quantity comes down, which for most subscriptions means at renewal.

The read-only shortcut

Sentsai runs these checks for Microsoft 365, read-only, in minutes. It reads the same signInActivity data through read-only delegated permissions, uses the more recent of each user’s interactive and non-interactive sign-in so that people who live in mobile apps are not mistaken for leavers, and flags licensed accounts idle for 180 days or more, E3 and E5 seats idle for 30 to 179 days as review candidates, and accounts that have never signed in. The free scan shows the total annual savings it identified, how many users it checked and how many compliance gaps it found. The itemized list, with every named account and license, costs 5% of the identified annual savings, with a $99 minimum. Sentsai changes nothing in your tenant; you decide what to remove.

Find the inactive licensed users in your tenant

Read-only, for Microsoft 365, in minutes. The free scan shows the total annual savings and the headline counts; the itemized, named list costs 5% of identified annual savings, $99 minimum.

Start your free scanSee a sample report first

Needs a one-time approval of read-only access from an administrator who can approve apps. Not an admin? Email this to yours.

Questions? support@sentsai.com

More from the blog

How to get a Microsoft 365 license usage report

Remove licenses from disabled users with PowerShell