Driverless Rigol DS1054Z screen capture over LAN

Capture the display of a Rigol DS1000Z series oscilloscope by LAN only, using LXI SCPI commands. No USB, no VISA, no IVI and no Rigol drivers required

Similar projects worth following
'' is a Python script that captures whatever is displayed on the screen of a Rigol DS1000Z series oscilloscope.

It can save data as a CSV or as a WYSIWYG PNG or BMP.

For this, SCPI (Standard Commands for Programmable Instruments) are sent from the computer to the oscilloscope, using the LXI (LAN-based eXtensions for Instrumentation) protocol over a Telnet connection.

The computer and the oscilloscope are connected together by a LAN (Local Area Network).
No USB (Universal Serial Bus), no VISA (Virtual Instrument Software Architecture),
no IVI (Interchangeable Virtual Instrument) and no Rigol drivers are required.
Python 2 with pillow imaging library is required. PIL is no longer supported. Python 3 is not supported.

Tested with Windows 10, Python 2.7.12, pillow and Rigol DS1104Z (a fully upgraded DS1054Z oscilloscope).

Tested with Linux Ubuntu 16.04.1, Python 2.7.12 and pillow.

Setup (please see for the latest instructions):

  • For Windows, install Python 2.7.12 from Python is already installed in Ubuntu.
  • Download and unzip DS1054Z_screen_capture
  • Install pillow imaging library. Installation steps are in the file.
  • Connect together the computer and the oscilloscope (by LAN).
  • To capture an image from the oscilloscope display and save it to the computer disk, open a Command Prompt or a Terminal, then run


python png


You can capture exactly what is seen on the oscilloscope display, including oscilloscope menus:

3D Printing AVR Arduino Art Audio Automation BeagleBone Bluetooth Cameras Clock Drones Environment Hardware IoT LED Medical Music Radio Raspberry Pi Remote Control Robotics Rockets Satellites Science Security Software Virtual Reality Wearables

  • 1 × Rigol DS1054Z Oscilloscope Rigol DS1054Z fully upgraded to DS1104Z
  • 1 × PC (Personal Computer) PC with Windows or Linux
  • 1 × LAN LAN connection between the PC and the oscilloscope

  • v1.0.0 released

    RoGeorge09/30/2016 at 12:54 3 comments

    First released version, v1.0.0:

    - Querry *OPC? instead of waiting 1 second between commands.
    - Added logging file, ''.

  • Update to use the 'pillow' Python library instead of 'PIL'

    RoGeorge08/13/2016 at 12:40 0 comments

    PIL is a deprecate Python library. In order to keep the '' script compatible with current and future versions of Python 2, for both Windows and Linux, from now on the script is using 'pillow' library instead of 'PIL'.

    If you already have 'PIL' installed, it MUST be uninstalled before installing 'pillow'.

    The updated version of the '' and installation steps for Python and 'pillow' can be found at

  • [SOLVED] A painfully slow LAN on Windows and a wasted weekend.

    RoGeorge06/01/2015 at 23:09 1 comment

    Problem: LAN speed for TCP is more then 100 times slower then expected. Why?

    Because Windows implemented it's own "smart" algorithms instead of following RFCs. I found out (the hard way) that starting from Vista, the TCP regulations were disregarded by Microsoft, resulting in unpredictable side effects like speed limitations for high speed Internet, or total collapse of the transfer speed, like in this case.

    Long story short, what slow down the transfer between the oscilloscope and the PC is a Microsoft algorithm that alter RWIN (TCP Receive WINdow) size in a proprietary way, with heuristic algorithms that override network settings, and no way to really tweak the parameter.

    Sollution: Use Linux.

    I will post some benchmarks after cleaning the Python code.


    LATER EDIT: It has been passed a year and a half, and now I couldn't reproduce the slow transfer any more. WireShark shows now the transfer time for the first 250 000 bytes is about the same:

    transfer time = 0.066444
    transfer time = 0.067693

  • "Memory lack in waveform reading!"

    RoGeorge05/29/2015 at 02:37 0 comments

    Trying to extract the full 24 million points memory buffer in one request will display on the oscilloscope screen the error message "Memory lack in waveform reading!", and the data transfer will be interrupted. With byte instead of ASCII mode, a bigger chunk of data can be extracted, but still incomplete.

    In order to overcome this issue, the only successful way so far was to repeatedly extract consecutive chunks of data from the memory buffer. This idea seems to work, but right now the code is just a mess resulted after testing different approaches, and is painfully slow.

    The code was pushed to GitHub as is, and will be cleaned and optimized in the next version.

    Please note that for CSV memory buffer data extraction, the oscilloscope must be in STOP mode. RUN mode is allowed only when reading displayed traces, not memory data.

    3D Printing AVR Arduino Art Audio Automation BeagleBone Bluetooth Cameras Clock Drones Environment Hardware IoT LED Medical Music Radio Raspberry Pi Remote Control Robotics Rockets Satellites Science Security Software Virtual Reality Wearables

  • New capability added: Export displayed traces as CSV

    RoGeorge05/24/2015 at 23:11 3 comments

    Added data capture and save as text in CSV (Comma Separated Values) format.

    • To capture displayed channels as CSV, type:
      python.exe csv
    • All channels displayed by the oscilloscope screen are saved in the CSV file, including the "MATH" channel.
    • The CSV file can be used as a data exchange format with other programs. As an example, this is a captured CSV file imported in a spreadsheet. The chart was not copied from the oscilloscope, it was generated by the spreadsheet.

    • To capture the WYSIWYG oscilloscope display, type:
      python.exe png
      Notice the differences between the chart/data look and the display look:

    For a better CSV data usability, the following features needs to be implemented:
    • data timestamp
    • save/decode raw data

    Other nice to have:

    • save all the oscilloscope settings together with the CSV data
    • labels for the CSV channels
    • test if Decode1 and Decode2 can be exported

    3D Printing AVR Arduino Art Audio Automation BeagleBone Bluetooth Cameras Clock Drones Environment Hardware IoT LED Medical Music Radio Raspberry Pi Remote Control Robotics Rockets Satellites Science Security Software Virtual Reality Wearable

  • Ported for Linux

    RoGeorge05/23/2015 at 00:06 0 comments

    Tested on a VMware machine with Debian 7.7.0, Python 2.7.3 and PIL. Python and PIL were already present in the default Debian installation.

    To run it in Linux:

    • download the project from GitHub
    • open a Terminal
    • go to the project's directory
    • type

    3D Printing AVR Arduino Art Audio Automation BeagleBone Bluetooth Cameras Clock Drones Environment Hardware IoT LED Medical Music Radio Raspberry Pi Remote Control Robotics Rockets Satellites Science Security Software Virtual Reality Wearable

View all 6 project logs

Enjoy this project?



Grant Giesbrecht wrote 10/27/2019 at 07:16 point

Man this is fantastic, especially considered how dang slow these scopes are at saving PNGs to flash drives  (mine has taken ~5 minutes sometimes ¯\_(ツ)_/¯ ). I was going to go write a script of my own, then found yours which is super nicely polished and way better than what I would have made :). Thanks a million - you saved me a ton of time!

A few notes: 

I noticed you don't say anywhere that it's been tested on a mac - it has now! I followed your installation instructions and got it working *almost* with no problems. I had to comment out "log_running_python_versions()" to prevent an error with pip.get_installed_distributions(). If you're interested DM me and I can give you more info. I'd also be happy to test any fixes if you don't have a mac handy and are interested in making it macOS friendly. 

I was using a DS1074Z Plus. The 'plus' in the name threw off the scope model checker code you've got, prompting the program to warn that no DS1000Z series scope was detected. It's super easy to get past because of the option to ignore the warning, but you could add a check for "plus" models too. I added this "plus" case to my copy of your code and it works great!

  Are you sure? yes | no

carguy79 wrote 04/20/2019 at 15:19 point

Complete newb here. I got this to work fine. How would I go about using this to make a constant log?

I'm using my DS1054z to trace automotive sensors, what I'm looking for is a way to go back and view the oscope waveform after the vehicle has stalled.

Any help would be greatly appreciated.

  Are you sure? yes | no

NASCO wrote 03/10/2017 at 06:11 point

Oh Noes!  The Github link is dead :(

  Are you sure? yes | no

peewag wrote 11/11/2016 at 11:53 point

Hi, congratulation to this project. It's verry useful.

I had an problem with the "get_memory_depth(tn)" function while capturing the csv-data.

I added some cast-operator and now it works.

# mdep = h_grid * scal * srate
        mdep = h_grid * float(scal) * float(srate)



  Are you sure? yes | no

GiorgioFoX wrote 08/16/2016 at 11:40 point

uhm: I'm trying with DS4000, after commenting these lines I have this errors:

$ python bmp 

Instrument ID: RIGOL TECHNOLOGIES,DS4034,DS4A182500000,00.02.03

Receiving screen capture...

Traceback (most recent call last):

  File "", line 152, in

    im =

  File "/Library/Python/2.7/site-packages/PIL/", line 2317, in open

    % (filename if filename else fp))

IOError: cannot identify image file <StringIO.StringIO instance at 0x10961a7e8>

and with CSV:

$ python csv 

Instrument ID: RIGOL TECHNOLOGIES,DS4034,DS4A182500000,00.02.03

Active channels on the display: []

Traceback (most recent call last):

  File "", line 175, in

    depth = get_memory_depth(tn)

  File "/Users/giorgiofox/Desktop/RIGOL Data/DS1054Z_screen_capture/", line 28, in get_memory_depth

    return float(mdep)

ValueError: could not convert string to float:

any idea?

(my email address is giorgiofox(at) )

  Are you sure? yes | no

RoGeorge wrote 08/16/2016 at 12:00 point

It's hard for me to debug without a DS4000, sorry.

Maybe you should try other programs. @Teuniz wrote here, in the comments, that his software can download the CSV too, and it was working for DS6000:

  Are you sure? yes | no

RoGeorge wrote 08/16/2016 at 12:06 point

And there is one more driverless version to try, from @pklaus. His Python skills looks way better then mine:

  Are you sure? yes | no

GiorgioFoX wrote 08/16/2016 at 09:31 point

Hi! do you know if this is compatible with Rigol DS4000  series?
I need to extract CSV, but maybe commands are compatible..

  Are you sure? yes | no

RoGeorge wrote 08/16/2016 at 10:12 point

It might work, but I don't have a DS4000 to test it, so I don't know.

Just in case you want to give it a try, you need to comment out or delete the lines 119...123 from the file '':


if (id_fields[company] != "RIGOL TECHNOLOGIES") or \
(id_fields[model][:3] != "DS1") or (id_fields[model][-1] != "Z"):
print "ERROR: No Rigol from series DS1000Z found at ", IP_DS1104Z


These lines will stop the execution if the instrument ID is not from the DS1000Z series, but you can adjust the lines to accept your model, or simply remove them. Good luck!

  Are you sure? yes | no

GiorgioFoX wrote 08/16/2016 at 10:14 point

Tnx! I will try soon, and after this I will report (or fork a compatible version )



  Are you sure? yes | no

Stuart wrote 11/22/2015 at 19:41 point

This is so much better than Rigol's software!  Easy to install and worked first time.  Thank you so much for putting this together!

  Are you sure? yes | no

RoGeorge wrote 08/13/2016 at 05:21 point

I'm glad you like it.

  Are you sure? yes | no

Denis wrote 09/06/2015 at 16:40 point
Tested with MSO1074Z-S. Initially connection is refused but when I change DS1 to MSO in it sent .png successfully. Maybe you should add also testing for MSO string when *IDN? is executed.

  Are you sure? yes | no

RoGeorge wrote 09/06/2015 at 17:25 point

Well done, you nailed it!

I would like to add more devices, but I will not be able to test the result.
Still, the main problem is that I couldn't find the time yet to polish the code from the last version, which is very sloppy.

Anyway, your idea is very good. In the next version I will remove the check for the oscilloscope family.


  Are you sure? yes | no

Ryan wrote 09/04/2015 at 05:02 point

Cool project. I just got a MSO1104Z and can confirm this script works with my scope (at least for image capture). Instead of grabbing a BMP from the scope and converting to PNG in the script, I've found it to be much faster to ask the scope for PNG in the first place. This also removes the dependency for an image conversion library:

#!/usr/bin/env ruby

require 'socket'

sock =[0], 5555)
sock.write "display:data? ON,OFF,PNG\n"
(data = sock.getc) == '#' or fail "Unexpected response `#{data}'"
data ='%Y%m%d_%H%M%S.png'), 'wb') { |f| f << data }

  Are you sure? yes | no

RoGeorge wrote 09/06/2015 at 17:17 point

You are lucky to have a MSO able to send PNG.

My DS1054Z doesn't like that SCPI command ("display:data? ON,OFF,PNG\n"). It returns "command error". Also, in the programming manual of DS1054Z there is no mention about PNG format.

  Are you sure? yes | no

Teuniz wrote 06/13/2015 at 10:48 point

You can download the full 12 (or 24) Mpoints from memory using this (opensource) software:

You don't need to install any drivers, at least the DS1054Z is plug and play.

  Are you sure? yes | no

RoGeorge wrote 06/13/2015 at 15:03 point

It's great to see similar projects.

Thanks for sharing!

  Are you sure? yes | no

peter jansen wrote 05/23/2015 at 01:58 point

Brilliant!  Is there an easy way to capture the data buffer over the LAN as well, without all those cursed drivers?

  Are you sure? yes | no

RoGeorge wrote 05/23/2015 at 11:35 point

Thanks! Yes, it should be possible to transmit the captured data after each trigger, using the SCPI command ":WAVeform:DATA?". Added this to the TODO list, together with a CSV (Comma Separated Values) text export.

What it doesn't looks possible so far, is to continuously stream the row ADC (Analogue to Digital Converter) data out of the oscilloscope, so the oscilloscope could be used as a 1 GSa/s data acquisition system. It seems like the Rigol DS1000Z series does not have streaming capabilities.

  Are you sure? yes | no

peter jansen wrote 05/23/2015 at 19:10 point

If you added the feature to export the data buffer with a CSV export over LAN without the drivers, that would be incredible.  Such a wonderful scope in so many ways, but I have no idea what they were thinking with the software for connecting it to a PC. 

  Are you sure? yes | no

RoGeorge wrote 05/24/2015 at 23:26 point

Wish granted, sir!

  Are you sure? yes | no

RoGeorge wrote 05/28/2015 at 03:36 point

Indeed, the full 12 million data points extraction is tricky. 

It should have been worked out of the box, but instead, this feature really messed up my TODO list
# TODO: Use "waveform:data?" multiple times to extract the whole 12M points
                in order to overcome the "Memory lack in waveform reading!" screen message
# TODO: Detect if the osc is in RUN or in STOP mode (looking at the length of data extracted)
# TODO: Investigate scaling. Sometimes 3.0e-008 instead of expected 3.0e-000
# TODO: Add timestamp and mark the trigger point as t0
# TODO: Use channels label instead of chan1, chan2, chan3, chan4, math
# TODO: Add command line parameters file path
# TODO: Add browse and custom filename selection
# TODO: Create executable distributions
But don't worry, I'm almost there!

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates