First off you need to update Veeam to the latest release 12.3 as 9.5 is out of support and the new release has improvements to PS.
If you search the community there is a thread IIRC that has details about tape reports if that is the main goal. If not then just Google or ask AI to create one. Be careful due to your version be sure to specify it.
Updating the infrastructure would defintely be the best way to go.
In the meentine maybe the old “My veeam report Script” could help.
https://gist.github.com/smasterson/9136468#file-myveeamreport-ps1
It was created for veeam 9.5 so it might be worth a try.
Regards
Chalid
sorry, guys. upgrade infra is a different topic. I need show last 5 years report to regional business head. 30 mins discussion then a final call related to finance. - How much cost and time for upgrade.
First off you need to update Veeam to the latest release 12.3 as 9.5 is out of support and the new release has improvements to PS.
If you search the community there is a thread IIRC that has details about tape reports if that is the main goal. If not then just Google or ask AI to create one. Be careful due to your version be sure to specify it.
share weblink please
9.5 is going to be a bit of a wrench here, as will tape.
o https://forums.veeam.com/powershell-f26/get-tape-content-via-powershell-t22142.html
o https://forums.veeam.com/tape-f29/need-to-get-list-of-backups-on-tapes-t55625.html
o https://forums.veeam.com/tape-f29/see-the-content-of-a-tape-in-v12-t85276.html
o https://forums.veeam.com/powershell-f26/get-tape-content-via-powershell-t22142-60.html
o https://forums.veeam.com/tape-f29/best-way-to-find-a-file-on-tape-t56399.html
One of those should work for you for the tape reports as there isn’t a “good” built in one for what object is on what tape, but I really don’t remember which worked with v9.5. The one from user Wint (I think that was the name) should help for tape.
As for the rest, it’s going to depend heavily on the session history configuration: https://helpcenter.veeam.com/docs/backup/vsphere/history_settings.html?zoom_highlight=session+history&ver=120
Veeam prunes the session history by design to keep the database slim. But easiest way for the normal backups is to simply right-click the job and select “report” for each job.
You can similarly go to the Session History Tab and Shift + Click sessions for the same job type and then generate a report from there, but will need to inform that because of the session history pruning, likely VBR itself will have an incomplete record. If you’ve had VeeamOne monitoring the environment the entire time (or Enterprise Manager), likely you could pull it from those and set the range for All Time.
If still won’t work, best I can think of is if you had email notifications for jobs set up, you can gather up all the email notifications and parse through those.
Here is one for V12, but V12 and above uses a PowerShell module. Hint - You should upgrade 
You could take this and put it in AI and try to convert it to work with Veeam 9. Unfortunately I can’t test that.
This didn’t fully work, but it’s close The output looks like the following.
"Jobname","VMname","6/26/2025 7:14:00 AM",,"Disk","N/A"
I need to spend a bit more time to get the retention and tape portion working.
# Import Veeam PowerShell Module (V12+)
Import-Module Veeam.Backup.PowerShell
$report = @()
# Get all backup jobs
$jobs = Get-VBRJob
foreach ($job in $jobs) {
# Get associated backups (if any)
$backups = Get-VBRBackup | Where-Object { $_.JobId -eq $job.Id }
foreach ($backup in $backups) {
# Get latest restore points per backup
$restorePoints = Get-VBRRestorePoint -Backup $backup
foreach ($rp in $restorePoints) {
# Check storage type
$storageType = if ($rp.Type -eq 'Tape') { "Tape" } else { "Disk" }
# Get Tape details if applicable
$tapeMedia = @()
if ($rp.Type -eq 'Tape') {
$tapeInfo = Get-VBRTapeMedium | Where-Object { $_.MediaPoolId -eq $rp.MediaPoolId }
if ($tapeInfo) {
$tapeMedia = $tapeInfo | Select-Object -ExpandProperty Barcode
}
}
# Get retention policy (keep days)
$retentionDays = $backup.BackupStorageOptions.RetainDays
$report += PSCustomObject]@{
'Job Name' = $job.Name
'Object Name' = $rp.Name
'Backup Start' = $rp.CreationTime
'Retention (Days)'= $retentionDays
'Storage Type' = $storageType
'Tape Barcode(s)' = if ($tapeMedia) { ($tapeMedia -join ', ') } else { 'N/A' }
}
}
}
}
# Output to CSV
$report | Sort-Object 'Job Name' | Export-Csv "Veeam_Backup_Report_v12.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Report saved to Veeam_Backup_Report_v12.csv"
I can’t confirm this works, but it will look more like this.
# Load Veeam PowerShell Snap-In (for Veeam v11 and earlier)
Add-PSSnapin VeeamPSSnapin -ErrorAction SilentlyContinue
# Get all backup jobs
$jobs = Get-VBRJob
$report = @()
foreach ($job in $jobs) {
# Get last sessions (you can filter or select latest as needed)
$sessions = Get-VBRBackupSession | Where-Object {$_.JobName -eq $job.Name}
foreach ($session in $sessions) {
$backup = Get-VBRBackup | Where-Object {$_.JobId -eq $job.Id}
foreach ($object in $job.GetObjectsInJob()) {
$storageType = if ($backup.IsTapeBackup) { "Tape" } else { "Disk" }
$tapeMedia = $null
if ($backup.IsTapeBackup) {
$tapeSessions = Get-VBRTapeJobSession | Where-Object { $_.JobName -eq $job.Name }
foreach ($tapeSession in $tapeSessions) {
$tapeMedia += $tapeSession.TapeMedia | Select-Object -ExpandProperty Barcode
}
}
$report += PSCustomObject]@{
'Job Name' = $job.Name
'Object Name' = $object.Name
'Backup Start' = $session.CreationTime
'Retention (Days)'= $backup.GetOptions().BackupStorageOptions.RetainDays
'Storage Type' = $storageType
'Tape Barcode(s)' = if ($tapeMedia) { ($tapeMedia -join ', ') } else { 'N/A' }
}
}
}
}
# Export to CSV
$report | Sort-Object 'Job Name' | Export-Csv "Veeam_Backup_Report.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Report saved to Veeam_Backup_Report.csv"
Updating the infrastructure would defintely be the best way to go.
In the meentine maybe the old “My veeam report Script” could help.
https://gist.github.com/smasterson/9136468#file-myveeamreport-ps1
It was created for veeam 9.5 so it might be worth a try.
Regards
Chalid
Hi @rookie11
The Powershell Script that i mentioned ist for Veeam 9.5 and hast a Tape section. I would suggest to have a Look.

Regards
Chalid
First off you need to update Veeam to the latest release 12.3 as 9.5 is out of support and the new release has improvements to PS.
If you search the community there is a thread IIRC that has details about tape reports if that is the main goal. If not then just Google or ask AI to create one. Be careful due to your version be sure to specify it.
share weblink please
Here is the KB article with download link at the bottom - https://www.veeam.com/kb4696
Keep in mind since you are on 9.5 you cannot go straight to 12.3 as you will need to go to 11a first I believe.
use this scrpit:
Add-PSSnapin VeeamPSSnapIn
$jobs = Get-VBRJob
foreach ($job in $jobs) {
$sessions = Get-VBRBackupSession -Job $job | Sort-Object EndTime -Descending | Select-Object -First 1
foreach ($session in $sessions) {
$objects = Get-VBRBackupSession | Get-VBRTaskSession
foreach ($obj in $objects) {
>PSCustomObject]@{
JobName = $job.Name
ObjectName = $obj.Name
Status = $obj.Status
StartTime = $obj.Progress.StartTime
EndTime = $obj.Progress.StopTime
BackupSizeGB = imath]::Round($obj.Progress.TransferedSize / 1GB, 2)
RetentionPolicy = $job.Options.BackupStorageOptions.RetainCycles
StorageType = if ($job.IsTapeJob) { "Tape" } else { "Disk" }
}
}
}
}
I can’t confirm this works, but it will look more like this.
# Load Veeam PowerShell Snap-In (for Veeam v11 and earlier)
Add-PSSnapin VeeamPSSnapin -ErrorAction SilentlyContinue
# Get all backup jobs
$jobs = Get-VBRJob
$report = @()
foreach ($job in $jobs) {
# Get last sessions (you can filter or select latest as needed)
$sessions = Get-VBRBackupSession | Where-Object {$_.JobName -eq $job.Name}
foreach ($session in $sessions) {
$backup = Get-VBRBackup | Where-Object {$_.JobId -eq $job.Id}
foreach ($object in $job.GetObjectsInJob()) {
$storageType = if ($backup.IsTapeBackup) { "Tape" } else { "Disk" }
$tapeMedia = $null
if ($backup.IsTapeBackup) {
$tapeSessions = Get-VBRTapeJobSession | Where-Object { $_.JobName -eq $job.Name }
foreach ($tapeSession in $tapeSessions) {
$tapeMedia += $tapeSession.TapeMedia | Select-Object -ExpandProperty Barcode
}
}
$report += oPSCustomObject]@{
'Job Name' = $job.Name
'Object Name' = $object.Name
'Backup Start' = $session.CreationTime
'Retention (Days)'= $backup.GetOptions().BackupStorageOptions.RetainDays
'Storage Type' = $storageType
'Tape Barcode(s)' = if ($tapeMedia) { ($tapeMedia -join ', ') } else { 'N/A' }
}
}
}
}
# Export to CSV
$report | Sort-Object 'Job Name' | Export-Csv "Veeam_Backup_Report.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Report saved to Veeam_Backup_Report.csv"
this works i use before
@waqasali
$sessions = Get-VBRBackupSession -Job $job | Sort-Object EndTime -Descending | Select-Object -First 1
Get-VBRBackupSession doesn’t have a -Job parameter, that would be Get-VBRSession
I can’t confirm this works, but it will look more like this.
# Load Veeam PowerShell Snap-In (for Veeam v11 and earlier)
Add-PSSnapin VeeamPSSnapin -ErrorAction SilentlyContinue
# Get all backup jobs
$jobs = Get-VBRJob
$report = @()
foreach ($job in $jobs) {
# Get last sessions (you can filter or select latest as needed)
$sessions = Get-VBRBackupSession | Where-Object {$_.JobName -eq $job.Name}
foreach ($session in $sessions) {
$backup = Get-VBRBackup | Where-Object {$_.JobId -eq $job.Id}
foreach ($object in $job.GetObjectsInJob()) {
$storageType = if ($backup.IsTapeBackup) { "Tape" } else { "Disk" }
$tapeMedia = $null
if ($backup.IsTapeBackup) {
$tapeSessions = Get-VBRTapeJobSession | Where-Object { $_.JobName -eq $job.Name }
foreach ($tapeSession in $tapeSessions) {
$tapeMedia += $tapeSession.TapeMedia | Select-Object -ExpandProperty Barcode
}
}
$report += rPSCustomObject]@{
'Job Name' = $job.Name
'Object Name' = $object.Name
'Backup Start' = $session.CreationTime
'Retention (Days)'= $backup.GetOptions().BackupStorageOptions.RetainDays
'Storage Type' = $storageType
'Tape Barcode(s)' = if ($tapeMedia) { ($tapeMedia -join ', ') } else { 'N/A' }
}
}
}
}
# Export to CSV
$report | Sort-Object 'Job Name' | Export-Csv "Veeam_Backup_Report.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Report saved to Veeam_Backup_Report.csv"
Also, sorry to but in but I would not use this script on anything but a test lab. It will work, but it will be quite slow as:
- It’s fetching ALL sessions, which is incredibly slow, and it does so for each job repeatedly
- It will run Get-VBRBackup for EVERY SESSION RETURNED, basically burning CPU cycles potentially hundreds or even thousands of times
- It’s using unsupported .NET internal methods which may stop working as expected
- Most of the information the end report ends up with does not need Session nor Backup data
I revised the script, though I dropped the JobObjects for now as it can get unwieldly (you can return it by using Get-VBRJobObject and then joining the string outputs like I did for $usedTapes)
# Load Veeam PowerShell Snap-In (for Veeam v11 and earlier)
Add-PSSnapin VeeamPSSnapin -ErrorAction SilentlyContinue
# Get all backup jobs
$allJob = @()
$allJob += Get-VBRJob
$allJob += Get-VBRTapeJob
$reportFull = @()
Foreach($j in $allJob){
If($j.Type -eq "BackupToTape"){$storageType = "Tape"}else{$storageType = "Block or S3"}
If($j.Type -eq "BackupToTape"){
$usedTapes = @()
$fullMpTapes = ($j.FullBackupMediaPool.Medium | Where-Object {$_.MediaSet -like "Media*"}).Barcode
$incMpTapes = ($j.IncrementalBackupMediaPool.Medium | Where-Object {$_.MediaSet -like "Media*"}).Barcode
$usedTapes += $fullMpTapes
$usedTapes += $incMpTapes
}
$jobSchedule = Get-VBRJobScheduleOptions -Job $j
$lastRunLocalUTC = $jobSchedule.LatestRunLocal.ToUniversalTime()
$jobOptions = Get-VBRJobOptions -Job $j
$data = /PSCustomObject]@{
'Job Name' = $j.name
'Last Backup Start Time UTC' = $lastRunLocalUTC
'Retention Type' = If($j.Type -eq "BackupToTape"){'N/A'}else{$jobOptions.BackupStorageOptions.RetentionType}
'Retention Value' = If($jobOptions.BackupStorageOptions.RetentionType -eq "Days"){$jobOptions.BackupStorageOptions.RetainDaysToKeep}else{$jobOptions.BackupStorageOptions.RetainCycles}
'Storage Type' = $storageType
'Used Tapes in Media Pool' = If($j.Type -ne "BackupToTape"){'N/A'}else{$usedTapes -Join "; "}
}
$reportFull += $data
Remove-Variable data
Remove-Variable storageType
Remove-Variable usedTapes -ErrorAction SilentlyContinue
Remove-Variable fullMpTapes -ErrorAction SilentlyContinue
Remove-Variable incMpTapes -ErrorAction SilentlyContinue
Remove-Variable jobSchedule
Remove-Variable lastRunLocalUTC
Remove-Variable jobOptions
}
$reportFull | Export-Csv -NoTypeInformation "Veeam_backup_report.csv"
Much faster, returns the same information without having to take the scenic route for a lot of the information.
As a general rule, avoid Get-VBRBackupSession, Get-VBRSession, Get-VBRBackup, and Get-VBRRestorePoint as much as possible, or use their filters if it’s essential to get data. These are very useful cmdlets, but also can be very slow if run without any filtering. It’s best to explore what you have on an existing object whenever possible, as we have a LOT of cross linking in the properties. There are tools for Powershell that let you expand an object and see all its methods and properties, or you can export an object with Export-CliXml and get a nice plain-text file to read at your leisure.
thanks for your script , it works. I will rephrase my requirement “I need a detailed backup report which contains - server name\object name, restore points(all of them), backup start time , data retention, storage(disk\tape), tape number etc “. it is kind of onetime exercise. I will be glad to run high number of CPU cycles bcoz to fetch all restore points i understand script or command will query whole internal DB.