Every Microsoft 365 tenant carries seats nobody is using. Some were bought for a hiring plan that slipped. Some came back to the pool when someone left. And there’s usually a block of Copilot licenses that never got past the pilot group. They all sit in the available count on the Licenses page, and Microsoft bills for every one of them until you cut the quantity, which on most subscriptions means waiting for renewal. This isn’t a small leak, either. Zylo’s 2026 SaaS Management Index found the average organization uses only 54% of its SaaS licenses. Unassigned seats are the easiest part of that waste to fix, because you don’t need usage data to find them. You just need the right number, and the native tools rarely give it to you cleanly.
Quick answer: To find unassigned Microsoft 365 licenses, open the Microsoft 365 admin center and go to Billing > Licenses. The Available count for each product is your unassigned number. For a tenant-wide view, run
Get-MgSubscribedSkuin Microsoft Graph PowerShell and subtractConsumedUnitsfromPrepaidUnits.Enabled. Then filter out free, trial and company-level SKUs before you put a dollar figure on it.
Key takeaways
- An unassigned license is a paid seat with no user attached. It costs exactly what an assigned seat costs.
- The admin center, Entra and Graph all show the gap between purchased and assigned. None of them correct it for free SKUs, trials or blocked accounts.
- Blocking a leaver’s sign-in doesn’t free their license. Those seats count as assigned and never show up as unassigned.
- Unassigning saves nothing on its own. The quantity has to come down inside a short window around purchase or renewal.
- Zero unassigned isn’t the target. Keep a small buffer sized to how many people you hire and how fast you can buy.
What is an unassigned Microsoft 365 license?
An unassigned Microsoft 365 license is a seat your organization has purchased on a subscription but hasn’t attached to any user. You pay full price for it, and nobody can use it.
That’s all it is. The seat exists on the subscription, it shows up on your invoice, and it does nothing until someone assigns it.
Most of them arrive the same few ways. A leaver’s account gets deleted and the license drops back into the pool. Procurement buys 50 seats for a team that ends up hiring 35. A Copilot pilot gets 100 licenses, 60 get assigned, and the other 40 wait for a rollout that keeps slipping a quarter.
The terminology gets muddled, though. People say “unassigned” when they mean “unused,” and half the search results for this topic are really about inactive users. These four states look similar on a dashboard but need different handling:
| License state | What it means | Costs money? | Where you see it |
| Unassigned | Purchased seat with no user attached | Yes, full price | Available count on Billing > Licenses |
| Disabled but licensed | Seat assigned to an account with sign-in blocked | Yes, and it hides as “assigned” | Active users, filtered by sign-in status |
| Unused (inactive) | Assigned to an enabled account that isn’t using the service | Yes | Usage reports, last sign-in dates |
| Unlicensed user | Account with no license at all | No | Active users, filtered to unlicensed |
Only the first row shows up as unassigned in any native tool. The second and third count as assigned everywhere, and in plenty of tenants they’re the bigger pile.
How do you find unassigned licenses in Microsoft 365?
Compare purchased against assigned for every SKU. The Microsoft 365 admin center shows it product by product, Microsoft Graph gives it to you for the whole tenant in one query, and Turbo360 Tenant Manager turns it into a costed, corrected number.
Which method fits depends on tenant size, how often you need the answer, and who’s going to read it.
Method 1: The Microsoft 365 admin center
- Sign in at admin.microsoft.com as a Global Reader, License Administrator or Billing Administrator.
- Go to Billing > Licenses.
- Read the Assigned and Available columns for each product. Available is your unassigned count.
- Click into a product to see who holds each seat and which groups assign it.
For a small tenant with four or five SKUs, this is honestly enough. It falls apart at 30 products across several billing accounts, because you’re reading them one at a time and nothing adds up to a dollar figure.
Method 2: The Microsoft Entra admin center
In the Entra admin center, go to Identity > Billing > Licenses > All products. You get the same split: total purchased against total assigned, per product.
One thing changed here, and a lot of older guides still haven’t caught up. Microsoft stopped supporting license assignment in the Entra admin center and Azure portal from September 2024. You can still view licenses in Entra, but assigning or removing them, including group-based licensing, now happens in the Microsoft 365 admin center. So Entra is a read-only check for this job. Useful if your identity team lives there. Not where you fix anything.
Method 3: Microsoft Graph PowerShell
For a tenant-wide view, query the subscribed SKUs directly. The unassigned count per SKU is the enabled prepaid units minus the consumed units.
Connect-MgGraph -Scopes "Organization.Read.All"
Get-MgSubscribedSku |
Select-Object SkuPartNumber, CapabilityStatus,
@{n='Purchased'; e={$_.PrepaidUnits.Enabled}},
ConsumedUnits,
@{n='Unassigned'; e={[math]::Max(0, $_.PrepaidUnits.Enabled - $_.ConsumedUnits)}} |
Sort-Object Unassigned -Descending
Schedule it and you get a monthly snapshot. Keep the snapshots and you get a trend, which the admin center never shows you.
Method 4: The Microsoft Graph API directly
If you’re feeding a dashboard or an automation, call the REST endpoint instead:
GET https://graph.microsoft.com/v1.0/subscribedSkus
Each subscribedSku in the response carries prepaidUnits.enabled, consumedUnits, appliesTo and capabilityStatus. Same subtraction, same result. As MVP Vasil Michev points out in a Microsoft Q&A answer, the unassigned figure isn’t exposed directly. You calculate it.
Method 5: Turbo360 Tenant Manager
Turbo360 Tenant Manager reads the same tenant data and does the correction and costing for you. It shows every paid seat as active, idle or unassigned, along with what the unused ones cost each month, priced at what you actually pay rather than list. It also surfaces the seats the other four methods count as assigned: disabled, inactive and never-signed-in users still holding licenses.
| Method | Best for | Corrects for free and trial SKUs | Catches disabled-but-licensed seats | Shows cost |
| Microsoft 365 admin center | Small tenants, one-off checks | No, you judge by eye | No | No |
| Entra admin center | Identity teams checking totals | No | No | No |
| Graph PowerShell | Admins comfortable scripting | Only if you add the filter | Only if you extend the script | Only if you add a price list |
| Graph API | Feeding your own dashboard | Only if you build it | Only if you build it | Only if you build it |
| Turbo360 Tenant Manager | IT and FinOps teams reporting before renewal | Yes | Yes | Yes, at your own pricing |
What are the limitations of Entra ID and Microsoft Graph for license management?
Entra and Graph give you accurate raw counts, but no prices, no renewal context, no correction for free SKUs or blocked accounts, and no safe way to act on what you find. Everything past the subtraction is a script you build and maintain yourself.
None of this makes the native tools bad. They’re the source of truth. But there’s a real gap between “the data exists” and “someone can make a renewal decision with it.” Here’s where it shows:
- No money in the data.
subscribedSkusgives you units, not dollars. Turning 40 unassigned seats into a figure finance will act on means keeping your own price list, per SKU, per agreement, and updating it every time Microsoft changes list prices (as it did on 1 July 2026). - SKU codes, not product names. You get
SPE_E3, not “Microsoft 365 E3.” You’ll map them against Microsoft’s product names and service plan identifiers list, and that list changes. - Free and viral SKUs pollute the count. Some show thousands of units nobody paid for. More on that in the next section.
- Blocked accounts are invisible. A disabled user still holding E5 counts as consumed. The unassigned number never includes them.
- Activity data costs extra. Reading
signInActivityfrom Graph to find inactive users requires Entra ID P1 or higher. And usage reports conceal user names by default until an admin turns that setting off. - Group-based licensing has strings attached. It’s the right way to assign licenses, but every member of a licensed group needs an Entra ID P1 license (or a suite that includes it), and assignment errors leave users stuck without a seat while the pool looks bigger than it is.
- Renewal dates live somewhere else. Seat counts and renewal dates come from different places, so lining up “what’s spare” with “when can I cut it” is a manual join.
- No guardrails on change. Graph will happily remove a license from a mailbox someone in legal still needs. There’s no approval step, and Entra’s audit log retention is short (7 days on the free tier, 30 days with P1 or P2), so the history of who changed what fades fast.
- One tenant at a time. If you’re an MSP or run several tenants after an acquisition, you’re running the same scripts N times and stitching the output together.
The usual result? A script that works well for three months, then breaks when the person who wrote it moves teams.
Why is your unassigned license count wrong?
Because the raw number mixes billable seats with free, trial and company-level SKUs, and it can’t see paid seats sitting on blocked accounts. It overstates waste in some places and understates it in others.
Run the Graph query on any tenant older than a couple of years and something odd shows up near the top. A SKU with thousands of unassigned units. Nobody bought those.
What inflates the count
Free and viral SKUs. Microsoft drops placeholder SKUs into tenants for free and self-service offerings. Power Automate Free (FLOW_FREE) typically shows 10,000 units, and some tenants see a million Power BI free licenses that aren’t billed at all. Leave one in the math and your “waste” is bigger than your whole M365 bill.
Trials. They look identical to paid subscriptions in the subtraction and cost nothing until someone converts them. Check Billing > Your products for anything marked as a trial.
Company-level SKUs. Each SKU has an appliesTo value of User or Company, and only User SKUs can be assigned. A Company SKU will never have users on it.
Seats you already owe. When group-based licensing fails because a subscription ran out, those users wait in an error state. Free up a few seats and the available count ticks up, but those seats belong to the people stuck in the queue. Check the licensing errors before you call anything surplus.
A corrected version of the query that handles the first three:
$freeSkus = @('FLOW_FREE','POWER_BI_STANDARD') # extend with your tenant's free SKUs
Get-MgSubscribedSku |
Where-Object {
$_.AppliesTo -eq 'User' -and
$_.CapabilityStatus -eq 'Enabled' -and
$_.SkuPartNumber -notin $freeSkus
} |
Select-Object SkuPartNumber,
@{n='Purchased'; e={$_.PrepaidUnits.Enabled}},
ConsumedUnits,
@{n='Unassigned'; e={[math]::Max(0, $_.PrepaidUnits.Enabled - $_.ConsumedUnits)}} |
Sort-Object Unassigned -Descending
Trials still need a manual check. They don’t carry an obvious flag in this output.
What hides from the count
This is the bigger problem, honestly.
A leaver whose sign-in is blocked keeps their license. Blocking doesn’t release it, so the seat counts as consumed and never appears as unassigned. Same goes for shared mailboxes that got a full license because they started life as a user account, and service accounts built from a template with E3 attached.
Finding the blocked-but-licensed accounts takes one query:
Connect-MgGraph -Scopes "User.Read.All"
Get-MgUser -Filter "accountEnabled eq false" -All `
-Property DisplayName, UserPrincipalName, AssignedLicenses |
Where-Object { $_.AssignedLicenses.Count -gt 0 } |
Select-Object DisplayName, UserPrincipalName,
@{n='LicenseCount'; e={$_.AssignedLicenses.Count}}
In a lot of tenants this list is longer than the unassigned pool itself. So the real “spare seats” number is closer to this: corrected unassigned, plus disabled-but-licensed, minus seats owed to licensing errors. That’s the one worth taking into a renewal conversation.
Do unassigned Microsoft 365 licenses cost money?
Yes. Microsoft bills on the number of licenses purchased, not the number assigned, so an unassigned seat costs exactly the same as one somebody uses every day.
Microsoft 365 E3 went from $36 to $39 per user per month on 1 July 2026. Say your tenant carries 40 unassigned E3 seats, which isn’t unusual for a 1,000-seat estate after a reorg:
- 40 × $39 = $1,560 a month
- Over a 12-month term, $18,720 for licenses nobody touched
That’s list price. Your EA or CSP rate moves the number, not the shape of the problem.
But here’s the part people miss. Finding those 40 seats three months into an annual term doesn’t get you $18,720 back. Most of that money is already committed until the next renewal. What the finding does buy you is two things: every joiner who gets one of those seats is a purchase you don’t make, and whatever is still spare near renewal comes off the quantity before the window closes.
Copilot is where it stings most per seat. The Microsoft 365 Copilot add-on is still $30 per user per month on an annual commitment, and it tends to get bought in round numbers for a pilot. Buy 100, assign 60, and the other 40 cost $1,200 a month with no user attached at all.
How many unassigned licenses should you keep?
Enough to cover joiners during your purchase lead time, plus about a week of joiners as safety, minus the leaver seats you reclaim in the same period. For most estates that’s a handful of seats per SKU, not a percentage.
Zero sounds tidy. It isn’t. Run the pool dry and the next new starter waits days for a mailbox while someone raises a purchase order, and that friction is exactly what pushes helpdesks into over-buying “just in case.”
The math is simple enough to do on a whiteboard:
Buffer = (joiners per week × lead time in weeks) + one week of joiners − (leaver seats reclaimed per week × lead time in weeks)
A worked example. A 1,000-seat E3 estate hires about 6 people a week. Buying more seats takes 2 weeks once you count internal approval. The leaver process reclaims about 4 seats a week.
- Joiners during lead time: 6 × 2 = 12
- Safety week: + 6
- Reclaimed during lead time: 4 × 2 = − 8
- Buffer: 10 seats
So of the 40 unassigned seats from earlier, 10 are a sensible buffer ($390 a month) and 30 are waste ($1,170 a month). That’s the number that goes in front of finance.
Notice what moves the buffer most. It’s the reclaim rate. A leaver process that takes three weeks instead of three days quietly forces you to carry more spare seats. Tenant Manager’s seat shortage and unused-license alerts are what let you run a buffer this tight without new starters getting stuck.
What should you do once you’ve found unassigned licenses?
Reassign spare seats before buying new ones, convert leavers’ mailboxes to shared before removing their licenses, clear group-licensing errors, remove duplicate licenses, then reduce the quantity inside the next allowed window.
Order matters. Pull a license off the wrong account and you’ve started the clock on a mailbox someone was counting on.
- Reassign before you buy. Check the available count before any new purchase. Group-based licensing does most of this for you: add joiners to the licensed group and they pull from the pool.
- Convert leavers to shared mailboxes, then unassign. A shared mailbox doesn’t need a license up to 50 GB. Above that, or on litigation hold, it still needs one, just a much cheaper one than the E5 it was carrying.
- Clear licensing errors. Fix the cause (seat shortage, conflicting service plans, missing usage location) and reprocess, then see what’s really left over.
- Remove duplicates. A user with Microsoft 365 E3 doesn’t need a standalone Exchange Online Plan 1 on top. These pile up after migrations.
Then the calendar takes over. Unassigning frees the seat but doesn’t change the bill. You have to reduce the subscription quantity, and when you’re allowed to do that depends on how you buy:
| How you buy | When you can reduce | What it means for unassigned seats |
| MCA, direct in the admin center (annual) | Within 7 days of buying or renewing | Finish the cleanup before renewal day, not after |
| CSP, New Commerce annual | Within 7 days of purchase, renewal or each mid-term add | Every mid-term add starts its own 7-day clock |
| CSP, New Commerce monthly | At the monthly renewal | More flexible, but a higher price per seat |
| Enterprise Agreement | At the enrollment anniversary, if the SKU is reduction-eligible | Start counting months ahead with your licensing partner |
The CSP rules are in Microsoft’s new commerce cancellation policy. The practical rule falls out of the table: run the cleanup 30 to 60 days before each subscription renews, and keep a renewal calendar per subscription, not per tenant. E3, Copilot, Visio and Teams Phone almost never renew on the same day.
Why manage unassigned licenses with Turbo360 Tenant Manager?
Because finding the number is the easy half. Tenant Manager closes the gaps Entra and Graph leave open: it costs the waste at your real prices, catches the seats native reports count as assigned, ties findings to renewal dates, and puts an approval step in front of every change.
Line it up against the limitations from earlier:
| Native gap | What Tenant Manager does instead |
| Units, not dollars | Shows active, idle and unassigned seats with their monthly cost, using your own license pricing |
| Blocked and inactive accounts look “assigned” | Flags disabled, inactive and never-signed-in users still holding licenses |
| Seat counts and renewal dates live apart | Tracks utilization and renewal dates together, with alerts before a subscription renews |
| Scripts to maintain | Gives recommendations at user, group and subscription level, each with the reason behind it |
| No guardrails on change | Turns every recommendation into a task someone approves, with a full change history including failed changes |
| One tenant at a time | Lets MSPs group customer tenants and manage each from one console |
A few things matter more than the feature list, though.
It starts read-only. You can connect it and find the waste without granting write access to anything, which tends to make security teams a lot more relaxed about the conversation. When you’re ready, scheduled cleanup removes licenses from disabled and inactive accounts using least-privilege permissions that only cover license changes.
It covers the expensive add-ons too: unused Copilot seats, overlapping licenses, and idle Defender, Entra ID and Intune seats, which are often the priciest licenses in the tenant and the least used.
And it sits next to your Azure cost data. If your FinOps team already reviews reservation utilization before every renewal (see our guide to Azure Reservations utilization monitoring), M365 subscriptions are the same kind of commitment with shorter windows. Same discipline, same owner, same place. That’s the gap admin tools like CoreView or AdminDroid and broad SaaS platforms like Torii or Zylo don’t really aim at.
How do you stop unassigned licenses from piling up again?
Assign by role-based group, release leaver seats the same day, put a review date on every add-on, and give one owner the renewal calendar.
Every tenant that’s been cleaned up once has the same story. Big effort before renewal, seats come off, everyone moves on. Eighteen months later the available count is right back where it was, because the cleanup fixed the number and left the process alone.
- Build licensing groups by role (knowledge worker, frontline, finance with Visio) and let membership do the assigning. Clear out old direct assignments once a population moves to groups, or users keep the direct one when they leave the group.
- Wire the leaver step to HR. Termination date hits, the mailbox converts, OneDrive goes to the manager, the user leaves their licensing groups. Measure days from leave date to seat reclaimed. Over a week means your buffer is working against you.
- Give every Copilot, Visio or Power BI Pro assignment a review date of 60 to 90 days. The business owner confirms the need or the seat goes back.
- No new seats for a SKU while its unassigned count sits above the agreed buffer. Thirty seconds for procurement to check.
And put M365 renewals on the same calendar your FinOps team already uses for Azure commitments. If you’re building that practice from scratch, our Azure FinOps guide covers the operating model.
Find unassigned and idle seats before your next renewal. See how Turbo360 Tenant Manager works, or book a demo.





