π₯ Recipe Β· User & Group Management
Bulk Update User Profile Attributes (e.g., City) via Microsoft Graph
Standardize directory profile fields across all employees using Microsoft Graph PATCH operations
Complexity
Intermediate
Impact
bulk-operation + directory-hygiene + user-profile + entra-id + automation
Context
Why This Matters
Directory profile attributes such as city, department, officeLocation, and country drive a surprising amount of downstream behavior in Microsoft 365: address book segmentation, dynamic group membership rules, Viva Insights aggregations, SharePoint profile cards, and conditional access named locations. When these fields are stale, empty, or inconsistent, reports look broken and automation misfires.
This recipe walks through a repeatable pattern for bulk-updating a single user attribute across every member account in the tenant. The working example sets city to a target value (e.g., Iasi) for all employees, but the same pattern applies to any writable property on the user resource.
When to run this
- Office relocation or new HQ address rollout
- HRIS sync drift β directory fell out of step with system of record
- Preparing attributes for a new dynamic group or Conditional Access rule
- One-time cleanup after a merger, acquisition, or rebrand
Expected Outcomes
After completing this recipe you will have:
- A filtered list of member users (excluding guests) whose attribute does not yet match the desired value
- The target attribute (e.g.,
city) updated to a single consistent value on every targeted account - A success/failure log suitable for change-management tickets and audit review
- A reusable script you can re-run for other attributes (
department,officeLocation,country,state, etc.)
Risks & Considerations
β οΈ Warnings & Gotchas
- Filter by
userType eq 'Member'β otherwise you will stamp guest accounts (B2B collaborators from partner tenants) with your internal city, which is incorrect and visible in their home tenant's profile card. - Service/shared/room accounts may not logically have a city. Consider additional exclusions for accounts matching naming conventions like
svc-*,room-*, or accounts with no assigned license. - Hybrid / directory-synced users: if your on-premises Active Directory is the source of authority (AAD Connect syncing the
lattribute), changes made in the cloud will be overwritten on the next sync cycle. Update the on-prem AD attribute instead, or block the attribute from sync. - Throttling: Microsoft Graph enforces per-app and per-tenant limits. For tenants with more than ~500 users, add a small delay between calls or use $batch (up to 20 requests per batch) to avoid HTTP 429 responses.
- No bulk undo. Always capture the current value for each user before writing, so you can roll back if the change is wrong.
- Dynamic groups whose membership rule references the attribute you are updating will reprocess membership β this can trigger license assignment changes, Conditional Access scope changes, and mail distribution changes. Review rules first.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| User.Read.All | Enumerate all users in the tenant to identify update targets. |
| User.ReadWrite.All | PATCH the profile attribute (city, department, etc.) on each user. |
| Directory.Read.All | Read userType and other directory metadata used for filtering. |
The fastest way to get this done: just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex Pro
Manual approach β Microsoft 365 Admin Center
The GUI is practical only when updating a handful of users. For tenants larger than ~20 accounts, use the API or PowerShell paths below.
Option A: Edit users one at a time
- Navigate to .
- Click a user's display name to open their profile panel.
- Select the Contact information tab.
- Click Manage contact information.
- Update the City field to the target value (e.g., Iasi).
- Click Save changes.
- Repeat for each user.
Option B: Bulk edit via CSV (limited attributes)
- Go to .
- Click β― (More actions) β Export users to download the current roster as CSV.
- Open the CSV and update the City column for the target users.
- Note: the admin center's built-in import does not support updating existing users β only creation. For bulk updates, proceed to the Graph API or PowerShell methods.
Option C: Microsoft Entra admin center
- Go to .
- Open each user, click Edit properties, scroll to Contact information, and update City.
- Click Save.
The GUI has no native "update all users" button. For anything beyond a few accounts, automate it.
Microsoft Graph API approach
This is a two-phase operation: enumerate then patch. Always enumerate and review targets before writing.
Phase 1 β Enumerate member users and their current city
GET https://graph.microsoft.com/v1.0/users?$select=id,displayName,userPrincipalName,city,userType&$top=999
Authorization: Bearer {access_token}Page through @odata.nextLink until all users are retrieved. In a large tenant you should filter server-side where possible:
GET /v1.0/users?$filter=userType eq 'Member' and city ne 'Iasi'&$count=true&$select=id,displayName,city
ConsistencyLevel: eventualThe ConsistencyLevel: eventual header is required when combining $filter with ne or $count on the users collection.
Phase 2 β PATCH each target user
PATCH https://graph.microsoft.com/v1.0/users/{user-id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
"city": "Iasi"
}Expected response: HTTP 204 No Content.
Phase 3 β Bulk via $batch (optional, recommended for >50 users)
Group up to 20 PATCH requests into a single batch call to reduce round-trips:
POST https://graph.microsoft.com/v1.0/$batch
Content-Type: application/json
{
"requests": [
{
"id": "1",
"method": "PATCH",
"url": "/users/9a30be11-2f5a-4339-8eee-a327064a87dc",
"headers": { "Content-Type": "application/json" },
"body": { "city": "Iasi" }
},
{
"id": "2",
"method": "PATCH",
"url": "/users/0d7fb357-de8f-4a7f-b8af-a92c3082e6fd",
"headers": { "Content-Type": "application/json" },
"body": { "city": "Iasi" }
}
]
}Common writable profile attributes
| Attribute | Example value |
|---|---|
city | "Iasi" |
country | "Romania" |
state | "IaΘi County" |
postalCode | "700000" |
streetAddress | "Str. Palat 1" |
officeLocation | "Building A, Floor 3" |
department | "Engineering" |
PowerShell approach β Microsoft.Graph module
PowerShell is the most ergonomic path for bulk profile updates. The script below enumerates all member users, filters those whose target attribute doesn't match, shows a preview for confirmation, then applies the change with progress reporting and a CSV rollback log.
Prerequisites
# Install the Microsoft Graph PowerShell SDK (one-time)
Install-Module Microsoft.Graph -Scope CurrentUser
# Connect with the scopes required for read + write
Connect-MgGraph -Scopes "User.Read.All","User.ReadWrite.All","Directory.Read.All"What the script does
- Retrieves every member user and the current value of the target attribute.
- Filters out users who already have the target value (idempotent re-runs).
- Writes a rollback CSV capturing the pre-change value for each user.
- Prompts for confirmation unless
-Confirm:$falseis passed. - PATCHes each user with
Update-MgUser, reporting progress. - Summarizes success/failure counts and writes a results CSV.
See the downloadable script below for the full implementation. To update any other attribute, change the -AttributeName parameter (e.g., department, officeLocation).
Next steps