I was recently reminded of an old article that I wrote back in 2013 demonstrating how to capture Virtual Machine screenshots using a couple of options that are available within vSphere. While the blog post is more than 10 years old, the guidance and options are still applicable for all recent vSphere releases.
I highly recommend folks give the original article a read, especially for the full background but I did want to provide some updated information for those interested in automating the capture of VM screenshots using both the vSphere API as well as the HTTP Handler methods.
Using vSphere API
While the original article included a vSphere SDK for Perl sample script, I figured most folks would prefer seeing a PowerCLI example using the vSphere API 🙂 Below is a functional example that uses the CreateSCreenshot_Task() API and waits for the task to complete, which then returns the location path for where the screenshot (PNG) file is stored and can be downloaded from.
$vm = Get-VM vcsa.primp-industries.local $task = $vm.ExtensionData.CreateScreenshot_Task() $task1 = Get-Task -Id ("Task-$($task.value)") $task1 | Wait-Task
To download the screenshot, we will use both the New-PSDrive to create virtual drive to vSphere Datas tore and then use Copy-DatastoreItem to transfer the screenshot to our local desktop. The commands below creates the logical drive mapping to the inventory hierarchy of the vSphere Datastore of where the screenshot is stored. In my example, the parent vSphere Datacenter for the vSphere Datastore is called Primp-Datacenter and vSphere Datastore name is sm-vsanDatastore.
New-PSDrive -PSProvider VimDatastore -Name sm-vsanDatastore -Root vmstore:Primp-Datacenter\sm-vsanDatastore Copy-DatastoreItem 'sm-vsanDatastore:\98f77763-01c1-f5d5-cbd5-ac1f6b1a4efa/vcsa.primp-industries.local-2.png' 'vcsa.primp-industries.local-2.png'
The benefit of using the vSphere API is that this method works with both vCenter Server as well as a standalone ESXi host, so the same code can be used in either environments in case you need to support both. To be able to use this vSphere API method, ensure the user performing the operation has the VirtualMachine.Interact.CreateScreenshot privilege.
Using HTTP Handler
Alternatively to the vSphere API, you can also leverage the HTTP handler method which now seems to only work when using a standalone ESXi host, at least as of vSphere 8. I was not able to connect to vCenter Server and quickly glancing at some of the rhttpproxy and vpxd logs, I noticed that this method may no longer be implemented.
For standalone ESXi host, you will perform an authenticated POST operation to a specific URL that includes the VM Managed Object Reference (MoRef) ID. The MoRef ID will differ from the vCenter MoRef ID even for the exact same VM as an ESXi host will generate a local MoRef ID compared to the one generated by vCenter Server. You can retrieve the desired MoRef ID by simply navigating to the desired VM using the ESXi Embedded Host Client and looking at your browser URL https://esxi.primp-industries.local/ui/#/host/vms/4435 where 4435 is the MoRef ID value or you can also use the vSphere API connected to an ESXi host to retrieve the list of MoRef IDs.
If you wish to automate the HTTP Handler method instead of opening up a browser, then you will need to perform an authenticated POST operation to the /screen endpoint as shown in the examples below.
cURL example:
curl -k -d 'user=root&password=VMware1!' -X POST 'https://esxi.primp-industries.local/screen?id=4435' -o screenshot.png
PowerShell example:
$webrequestParams = @{ Uri = 'https://esxi.primp-industries.local/screen?id=4435' Method = 'POST' Body = @{ user = 'root' password = 'VMware1!' } OutFile = "screenshot.png" } Invoke-WebRequest @webrequestParams -SkipCertificateCheck
To be able to use this HTTP handler method, ensure the user performing the operation has the VirtualMachine.Interact.CreateScreenshot privilege.
Raoul Schaffner says
thank you! is there a method to wake the screen in case its blacked out by the guest os?
William Lam says
Yes, you can use https://williamlam.com/2017/09/automating-vm-keystrokes-using-the-vsphere-api-powercli.html
Raoul Schaffner says
great! this will be my next pet project. 🙂 thanks again, r.
Sam says
@William,
Thanks for the article. I am interested in understanding this sentance you wrote:
'or you can also use the vSphere API connected to an ESXi host to retrieve the list of MoRef IDs'
I am taking this to mean that there is a way to start with a vCenter MoRef Id and via API, lookup the esxi's MoRef Id for the same object? Is that what you are meaning and is that possible to do via one if the API's?
Is there an API that I have not found where you can see a listing of the mappings from vCenter MoRef Id esxi MoRef Id? I have been looking at the VI/JSON api's (https://developer.vmware.com/apis/vi-json/latest/) and I have not found it.
William Lam says
MoRef ID scope are different across VC / ESXi, but the same object can be accessed either VC or ESXi vSphere API. There’s no REST endpoint for ESXi, only vSphere SOAP APi
Gregor Smerke says
@William
I am trying to use $Global:DefaultVIServer.SessionId to authenticate my Invoke-WebRequest -URI "https://my.vcenter.local/screen?id=MyMoRefID" call. If I use -Header @{"vmware-api-session-id" = $DefaultVIServer.SessionId} I get 401 (Unauthorized). Do you now a way how to reuse an already authenticated session with Connect-VIServer without having to provide username+password again to capture a screesnhot using HTTP handler?
Thanks
Gregor
William Lam says
This won't work, each HTTP handler screenshot requires auth, you can see this behavior if you manually do this for one VM and then attempt to do it for another, you'll be re-prompted for credentials
Jakub Trávník says
Hi William,
many thanks for your great work!
I have run into an issue and maybe you will have an idea what to do.
Sometimes I am getting this:
$vm.ExtensionData.CreateScreenshot_Task()
Type Value
---- -----
Task task-54578
Task task-54579
In vCenter I also see two tasks created and completed at the same time.
Any idea what could cause this behavior and how to deal with it?
I am on 8.0.3
Thanks!
Jakub Trávník says
Sorry, it was caused by multiple open VISessions... : )