Last Updated on February 17, 2024
From time to time you may notice that SharePoint Online does not display updated user photos in webparts.
You may see or experience something like this:
- Profile picture displayed in Office 365 Suite Bar: Yes
- Profile picture displayed in Office Delve: Yes
- Profile picture displayed in Outlook on the Web: Yes
- Profile picture displayed in Microsoft Teams: Yes
- Profile picture displayed in SharePoint People Web Part on a Modern SharePoint Page or trying to load user profile through custom web part on a classic SharePoint Page: No
There is a simple solution to this. Navigate to this URL in your SharePoint tenant:
- https://[tenant name here]-my.sharepoint.com/User%20Photos/Forms/Thumbnails.aspx?RootFolder=%2FUser%20Photos%2FProfile%20Pictures
This list stores three photos for each user in your Office 365 tenant.

The photos have the following naming convention and dimension requirements:
- username_tenantname_tld_SThumb.jpg: 42px x 42px
- username_tenantname_tld_MThumb.jpg: 78px x 78px
- username_tenantname_tld_LThumb.jpg: 300px x 300px
If my username was ryanclark, my tenant name was mrsp1, my TLD (top-level domain) was .com (could be .net, .org, .co, etc.), then we’d have the following:
- ryan.clark_mrsp1_com_SThumb.jpg
- ryan.clark_mrsp1_com_MThumb.jpg
- ryan.clark_mrsp1_com_LThumb.jpg
Save (and possibly overwrite) the three images in the user photos library and you should be good to go. You will have to do a hard refresh and/or clear your cache to see the results on the front-end.
Update: 11/9/2021
I’ve provided a PowerShell script below that can help with syncing photos from Exchange Online to SharePoint Online.
You must set the two input parameters ($siteURL and $SPOAdminPortalURL) on lines 96 and 97. In addition, you can enter an individual user’s email address or put in “All” when prompted for UserEmail.
Test on a test account first. Use at your own risk.
#Add references to SharePoint client assemblies and authenticate to Office 365 site as required for CSOM
Add-Type -AssemblyName System.Drawing
Function UploadImage ()
{
Param(
[Parameter(Mandatory=$True)]
[String]$SiteURL,
[Parameter(Mandatory=$True)]
[String]$SPOAdminPortalUrl,
[Parameter(Mandatory=$True, HelpMessage="Enter user email address or All for all mailboxes")]
[String]$UserEmail
)
#Default Image library and Folder value
$DocLibName ="User Photos"
$foldername="Profile Pictures"
Connect-ExchangeOnline
$siteConnection = Connect-PnPOnline -Url $SiteURL –Interactive -ReturnConnection
#NOTE: there is a bug in Set-PnPUserProfileProperty in which the ConnectPnPOnline must connect with the UseWebLogin option
# https://github.com/pnp/powershell/issues/277
$adminConnection = Connect-PnPOnline -Url $SPOAdminPortalUrl –UseWebLogin -ReturnConnection
$spoimagename = @{"_SThumb" = "48"; "_MThumb" = "72"; "_LThumb" = "200"}
$allUserMailboxes = Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox
Foreach($mailbox in $allUserMailboxes)
{
if(($mailbox.PrimarySmtpAddress -eq $UserEmail) -or ($UserEmail -eq "All")){
Write-Host "Processing " $mailbox.PrimarySmtpAddress
try{
#Download Image from Exchange online
$photo = Get-UserPhoto -Identity $mailbox.Identity
Write-Host "Exchange online image downloaded successful for" $mailbox.PrimarySmtpAddress
$username = $mailbox.PrimarySmtpAddress.Replace("@", "_").Replace(".", "_")
$Extension = ".jpg"
Foreach($imagename in $spoimagename.GetEnumerator())
{
#Covert image into different size of image
$ms = new-object System.IO.MemoryStream(,$photo.PictureData)
$img = [System.Drawing.Image]::FromStream($ms)
[int32]$new_width = $imagename.Value
[int32]$new_height = $imagename.Value
$img2 = New-Object System.Drawing.Bitmap($new_width, $new_height)
$graph = [System.Drawing.Graphics]::FromImage($img2)
$graph.DrawImage($img, 0, 0, $new_width, $new_height)
#Covert image into memory stream
$stream = New-Object -TypeName System.IO.MemoryStream
$format = [System.Drawing.Imaging.ImageFormat]::Jpeg
$img2.Save($stream, $format)
$streamseek=$stream.Seek(0, [System.IO.SeekOrigin]::Begin)
#Upload image into sharepoint online
$FullFilename=$username+$imagename.Name+$Extension
Add-PnPFile -Connection $siteConnection -Folder "User Photos/Profile Pictures" -FileName $FullFilename -Stream $stream
}
Write-Host "SharePoint online image uploaded successful for" $mailbox.PrimarySmtpAddress
#Change user Profile Property in Sharepoint onlne
$PictureURL=$SiteURL+$DocLibName+"/"+$foldername+"/"+$username+"_MThumb"+$Extension
Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName PictureURL -Value $PictureURL
Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName SPS-PicturePlaceholderState -Value 0
Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName SPS-PictureExchangeSyncState -Value 0
Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName SPS-PictureTimestamp -Value 63605901091
Write-Host "Image processed successfully and ready to display for" $mailbox.PrimarySmtpAddress
}catch{
$ErrorMessage = $_.Exception.Message
Write-Host "Failed to process " $mailbox.PrimarySmtpAddress -ForegroundColor red
Write-Host $ErrorMessage -ForegroundColor red
}
}
}
}
#Input parameter
$siteUrl="https://company-my.sharepoint.com/"
$SPOAdminPortalUrl = "https://company-admin.sharepoint.com/"
uploadimage -SiteURL $siteUrl -SPOAdminPortalUrl $SPOAdminPortalUrl
If you have any questions, reach out to me at any time.
Hey, Ryan. We’re dealing with this exact situation right now but the files for the affected users are not present in the URL you shared. They are there, however, for other users. As you described symptomatically, the following is true for impacted users: Profile picture displayed in Office 365 Suite Bar: Yes Profile picture displayed in Office Delve: Yes Profile picture displayed in Outlook on the Web: Yes Profile picture displayed in Microsoft Teams: Yes Profile picture displayed in SharePoint People Web Part on a Modern SharePoint Page or trying to load user profile through custom web part on a… Read more »
Hey Paul, For the users that don’t have pictures in the SharePoint User Profile library (the one I mentioned above), are you saying that their pictures are in fact showing in other places, like Delve? If so, you could take their photo from Delve and make the three photo sizes with the specific naming conventions I mentioned and upload them into the directory? CodeTwo has a tool that can help you to do this in bulk for free. After making sure the images are correctly in the User Profile library you will need to clear your cache. Let me know… Read more »
I am seeing the pictures all around O365, but for some not in the people web part. The profile pictures library has a mix of ‘real’ photo’s as you described, plus the problematic ones are just a placeholder silhouette file. I wonder if I delete these silhouette files if the user profile service (I have SharePoint server background, I don’t know if that is the term!) will populate them correctly?
Hi Mark,
You can delete the placeholders. Maybe try doing that with a single account at first. For the users with the silhouette images, do they have non-silhouette pictures (their actual real photo) in Delve?
Hi Ryan,
I have the exact issue you described. I have tried deleting the initial-only placeholders and re-adding them in, but still no photo shows up – it’s also not in the user profile photos which is odd – some are some aren’t. Perhaps it takes a while to sync? I also don’t know how to save and/or override the ones that there but don’t show up.
Hi Courtney,
Unfortunately, this could be a number of things. Feel free to contact me here if you’d like to discuss further –> https://www.mrsharepoint.com/contact/
We have this exact problem.
Users have uploaded their own pics, I can see a few of them in that URL, I can see a few more silhouttes, but most are just missing.
Is the only solution to this to go into Delve and save off people’s photos and then upload them all to this location – there must be some kind of synch that can be re-run?
I added a PowerShell script above that can help. Check it out when you’re able.
Connect-PnPOnline : A positional parameter cannot be found that accepts argument ‘â€Interactive -ReturnConnection
#NOTE: there is a bug in Set-PnPUserProfileProperty in which the ConnectPnPOnline must connect with the
UseWebLogin option
# https://github.com/pnp/powershell/issues/277
= Connect-PnPOnline -Url https://correct_domain-admin.sharepoint.com/ â€UseWebLogin’.
At C:\PSScripts\photo-sync.ps1:23 char:23
+ … onnection = Connect-PnPOnline -Url $SiteURL –Interactive -ReturnCon …
These 2 characters need to be corrected in the above script
Also getting few errors like:
Failed to process
Exception calling “.ctor” with “1” argument(s): “Buffer cannot be null.
Parameter name: buffer”
In order to run the above PowerShell Command you need to ensure that you have ExchangeOnlineManagement version 3.0+ installed. If not, you will see the following error: New-ExoPSSession : Connecting to remote server outlook.office365.com failed with the following error message : You can see the exact version of ExchangeOnlineManagement that you are running by opening an elevated instance PowerShell and running the following command: Get-InstalledModule This command will list out the modules you have installed. Look for the line that has a Name value of “ExchangeOnlineManagement” and note the version. You can then run the following command next: Uninstall-Module exchangeonlinemanagement… Read more »
Hello,
I am trying to run the script on our tenant, but a soon as I do I get the error that “-Connection” holds no sharepoint context. I think it’s having issues with the Add-PnPFile command.
Do you know what to do to fix this problem?