Back to blog
Ali KamalyAli Kamaly
August 14, 2026
12 min read
Instrument Automation

SCPI Command Cheat Sheet for Lab Instruments (2026 Reference)

The SCPI commands you actually use, organised by instrument class, with the universal commands, the syntax rules that trip people up, and where Keysight, Tektronix, and Rigol differ.

SCPI Command Cheat Sheet for Lab Instruments (2026 Reference)

SCPI is a text command language for test instruments, standardised at the top of the command tree and vendor-specific below it. That single fact explains why a cheat sheet is useful and why it can never be complete: *IDN? works everywhere, and the command to read a peak-to-peak voltage differs between every oscilloscope vendor.

This reference collects the commands that come up daily, organised by instrument class, with the syntax rules and the specific places vendors diverge.

Syntax rules

Short and long form. Documentation writes MEASure:VOLTage:DC?. The uppercase letters are the short form. MEAS:VOLT:DC? and MEASURE:VOLTAGE:DC? are both valid and identical. Mixed case is accepted. Use short form in scripts.

The colon. Separates levels of the tree. A leading colon returns to the root:

VOLT 3.3;:CURR 0.5          correct, CURR resolves from the root
VOLT 3.3;CURR 0.5           may fail, CURR is looked up under VOLT

This is the single most common chaining bug.

The question mark. Makes a command a query, which returns a response. Anything with ? needs a read. Anything without must not be read.

Parameters. Space-separated after the command, comma-separated between them.

CONF:VOLT:DC 10,0.0001

Channel lists. (@1) or (@1,3) or (@1:4) for a range.

VOLT 3.3,(@1)
OUTP ON,(@1,2)

Universal commands (IEEE 488.2)

These work on every compliant instrument.

CommandPurpose
*IDN?Manufacturer, model, serial, firmware
*RSTReset to default state
*CLSClear status and error queue
*OPC?Returns 1 when pending operations complete, blocks until then
*OPCSets the operation complete bit, non-blocking
*WAIWait for pending operations before continuing
*ESR?Read and clear the event status register
*STB?Read the status byte
*TST?Run self-test, 0 means pass
*SAV <n> / *RCL <n>Save and recall instrument state
SYST:ERR?Read the next error from the queue

**Start every script with *RST then *CLS, and check SYST:ERR? after every configuration block.** That is the entire error-handling discipline and it is worth more than the rest of this page.

Digital multimeter

CommandPurpose
CONF:VOLT:DC <range>,<res>Configure DC voltage
CONF:VOLT:AC <range>,<res>Configure AC voltage
CONF:CURR:DC <range>,<res>Configure DC current
CONF:RES <range>,<res>Configure 2-wire resistance
CONF:FRES <range>,<res>Configure 4-wire resistance
CONF:FREQConfigure frequency
CONF:TEMP TC,KConfigure thermocouple, type K
READ?Trigger and return a reading
INIT then FETC?Trigger, then fetch without re-triggering
MEAS:VOLT:DC? <range>,<res>Configure, trigger, and return in one command
VOLT:DC:NPLC <n>Integration time in power line cycles
`TRIG:SOUR IMM\EXT\BUS`Trigger source
SAMP:COUN <n>Samples per trigger

MEAS vs CONF plus READ. MEAS:VOLT:DC? resets the function and reconfigures every time, which is slow. For a loop, use CONF once outside and READ? inside. This alone can double throughput.

NPLC is the accuracy and speed dial. NPLC 10 is slow and quiet, NPLC 0.02 is fast and noisy. NPLC 1 rejects mains hum well and is a good default.

Power supply

CommandPurpose
VOLT <v>Set output voltage
CURR <a>Set current limit
VOLT? / CURR?Read back the setpoints
OUTP ON / OUTP OFFEnable and disable output
OUTP?Query output state
MEAS:VOLT?Measure actual output voltage
MEAS:CURR?Measure actual output current
INST:NSEL <n>Select channel
VOLT:PROT <v>Overvoltage protection level
CURR:PROT:STAT ONEnable overcurrent protection
STAT:QUES:COND?Query condition register, includes CC/CV state

Always set limits before enabling the output, and always read setpoints back. Supplies clamp silently to their range and report no error.

Oscilloscope

This is where vendors diverge most. Both columns shown.

PurposeKeysight InfiniiVisionTektronix
Autoset:AUTOSCALEAUTOSET EXECUTE
Timebase:TIM:SCAL <s>HORIZONTAL:SCALE <s>
Vertical scale:CHAN1:SCAL <v>CH1:SCALE <v>
Vertical offset:CHAN1:OFFS <v>CH1:OFFSET <v>
Trigger source:TRIG:EDGE:SOUR CHAN1TRIGGER:A:EDGE:SOURCE CH1
Trigger level:TRIG:EDGE:LEV <v>TRIGGER:A:LEVEL:CH1 <v>
Run:RUNACQUIRE:STATE RUN
Single:SINGLEACQUIRE:STOPAFTER SEQUENCE
Measure Vpp:MEAS:VPP? CHAN1MEASUREMENT:IMMED:TYPE PK2PK then ...:VALUE?
Measure frequency:MEAS:FREQ? CHAN1MEASUREMENT:IMMED:TYPE FREQUENCY
Waveform source:WAV:SOUR CHAN1DATA:SOURCE CH1
Waveform format:WAV:FORM BYTEDATA:ENC RIBINARY
Get data:WAV:DATA?CURVE?

Rigol scopes largely follow the Keysight-style colon-prefixed tree, which is why Rigol scripts often port from Keysight examples with modest changes. See automating a Rigol oscilloscope and Keysight vs Tektronix.

Function and arbitrary waveform generator

CommandPurpose
`FUNC SIN\SQU\RAMP\PULS\NOIS\DC\USER`Waveform shape
FREQ <hz>Frequency
VOLT <vpp>Amplitude, peak to peak by default
VOLT:OFFS <v>DC offset
`VOLT:UNIT VPP\VRMS\DBM`Amplitude units
FUNC:SQU:DCYC <percent>Square wave duty cycle
OUTP ON / OUTP OFFEnable output
`OUTP:LOAD 50\INF`Expected load impedance
BURS:STAT ONEnable burst mode
BURS:NCYC <n>Cycles per burst
PHAS <deg>Phase

`OUTP:LOAD` catches everyone. Generators default to assuming a 50 ohm load. Drive a high-impedance input with that default and you get exactly twice the amplitude you asked for. Set it to INF for scope inputs and most digital circuits.

Electronic load

CommandPurpose
`FUNC CURR\VOLT\RES\POW`Operating mode: CC, CV, CR, CP
CURR <a>Constant current setpoint
VOLT <v>Constant voltage setpoint
RES <ohm>Constant resistance setpoint
POW <w>Constant power setpoint
INP ON / INP OFFEnable and disable the load
MEAS:VOLT?Measure voltage at the terminals
MEAS:CURR?Measure current drawn
TRAN:STAT ONEnable transient mode
CURR:SLEW <a/s>Slew rate for current steps

Note that loads use INP rather than OUTP. Sending OUTP ON to a load is a common and confusing error.

Switch and matrix

CommandPurpose
ROUT:CLOS (@1001)Close a channel
ROUT:OPEN (@1001)Open a channel
ROUT:OPEN:ALLOpen everything, the safe reset
ROUT:CLOS?Query which channels are closed
ROUT:SCAN (@1001:1010)Define a scan list

Channel numbering is typically slot then channel, so 1001 is slot 1 channel 01. Always ROUT:OPEN:ALL before configuring, or you inherit whatever the previous test left closed.

The debugging loop

When a command does not work:

  1. 1

    Confirm the instrument is there. *IDN?. If this fails, the problem is the connection.

  2. 2

    Reset. *RST then *CLS. Removes leftover state.

  3. 3

    Send the single command in isolation, then immediately SYST:ERR?. Do not debug inside a loop.

  4. 4

    Read the error text. -113,"Undefined header" means the command does not exist on this model. -222,"Data out of range" means the value is wrong, not the command.

  5. 5

    Check the programming guide for that exact model. Not the family, not a generic reference.

Step 3 is the one people skip and it is the one that resolves most problems in under a minute.

Reading a SCPI response correctly

Responses are strings and they arrive in forms that trip up naive parsing.

Response formExampleParse with
Real number+3.30012000E+00float(response)
Integer+1int(float(response))
Boolean1 or 0bool(int(response))
Comma-separated+1.0,+2.0,+3.0[float(v) for v in response.split(",")]
Quoted string"No error"response.strip().strip('"')
Error pair-113,"Undefined header"code, text = response.split(",", 1)
Definite-length block#800001000<binary>query_binary_values

Two habits worth adopting. Always strip() before parsing, because trailing newlines are normal and int("1\n") works while bool("0\n") does not do what you expect. And never compare a boolean response as a string: "0" is truthy in Python, so if inst.query("OUTP?"): is true whether the output is on or off.

Chaining commands to cut round trips

Every command is a round trip, so a script sending 5,000 short commands spends real time on latency alone. Semicolons combine them into one transfer.

inst.write("VOLT 3.3;:CURR 0.5;:OUTP ON")

The leading colon after each semicolon returns to the root of the tree. Without it, the second command is resolved relative to the first one's node, which either errors or, worse, silently addresses something else.

Within one subsystem you can omit it deliberately:

inst.write("CONF:VOLT:DC 10;:VOLT:DC:NPLC 10")   # cross-subsystem, colon needed
inst.write("TRIG:SOUR IMM;COUN 1")               # same subsystem, no colon

Queries chain too, and the responses come back separated by semicolons:

response = inst.query("VOLT?;:CURR?")
voltage, current = (float(v) for v in response.strip().split(";"))

Combining a configuration block into one write typically removes 60 to 80 percent of the setup latency in a loop.

Temperature chamber and environmental

Less standardised than the instrument classes above, because many chambers speak Modbus rather than SCPI. Where SCPI is offered, this is the shape.

TaskTypical command
Set target temperature:SOUR:TEMP:SPO 85.0
Read current temperature:MEAS:TEMP?
Start the chamber:OUTP:STAT ON
Read stability flag:STAT:OPER:COND?
Set ramp rate:SOUR:TEMP:SLOP 3.0
Humidity setpoint:SOUR:HUM:SPO 50.0

The one to get right is the stability flag. Reaching a setpoint is not the same as being stable at it, and measuring during the overshoot is a common source of results that will not reproduce. Poll the stability condition and add a dwell on top of it:

def wait_stable(chamber, target_c, tol=1.0, dwell_s=600, timeout_s=7200):
    import time
    t0 = time.time(); stable_since = None
    while time.time() - t0 < timeout_s:
        actual = float(chamber.query(":MEAS:TEMP?"))
        if abs(actual - target_c) <= tol:
            stable_since = stable_since or time.time()
            if time.time() - stable_since >= dwell_s:
                return actual
        else:
            stable_since = None
        time.sleep(10)
    raise TimeoutError(f"chamber never stabilised at {target_c} C")

Status and synchronisation

The subsystem most people skip and then need at exactly the wrong moment. These are standard across every SCPI instrument.

CommandWhat it does
*OPC?Blocks until all pending operations complete, returns 1
*OPCSets the operation-complete bit, does not block
*WAIInstrument waits before processing further commands
*ESR?Standard event status register, clears on read
*STB?Status byte, does not clear
*CLSClear all status registers and the error queue
SYST:ERR?Pop one error off the queue

The practical pattern for anything slow (an acquisition, a sweep, a calibration) is to issue the command then *OPC?, which blocks until it finishes rather than guessing at a sleep:

scope.write("ACQuire:STATE ON")
scope.query("*OPC?")            # returns when the acquisition is genuinely done
value = scope.query("MEASUrement:IMMed:VALue?")

Start every session with *CLS so you are not reading errors left over from someone else's session. That single habit removes a category of confusing failures.

Common mistakes

  • Assuming a command is standard because it looks standard. Only the IEEE 488.2 * commands and the top of the tree are portable. Measurement commands are vendor territory.
  • Skipping `SYST:ERR?`. SCPI does not raise. A rejected command silently leaves the previous setting in place.
  • **Using a fixed sleep instead of *OPC?.** Either too slow or intermittently wrong, and the wrong one is worse.
  • Forgetting the short form is the capitalised part. :SOURce:VOLTage:LEVel and :SOUR:VOLT:LEV are the same command. Mixed partial abbreviations are not.
  • Omitting the leading colon after a semicolon. CMD1;:CMD2 restarts at the root. CMD1;CMD2 stays in the current subsystem, which is usually not what you meant.
  • Not clearing status at session start. *CLS first, every time.
  • Trusting a command copied from a different model in the same series. Firmware and options differ. Check *IDN? and *OPT?.

Where TestFlow fits

A cheat sheet helps with syntax. It does not tell you which commands a particular model needs in which order for a particular measurement, and that is the part that consumes the afternoon.

  1. 1

    Connect your instruments. Pick the manufacturer and model, paste the VISA address (USB, LAN, GPIB, or serial), and the agent knows what is on your bench. No bench yet? Use a placeholder address, build the full automation, and swap in the real address when you are in the lab.

  2. 2

    Tell the agent what to test, in plain English. For example, "run a VI sweep from 1 to 10 V in 1 V steps at 0.5 A load current," or "suggest the tests for a power-management device."

  3. 3

    The agent builds the complete workflow in seconds. Instrument-aware automation appears on the canvas, with the generated scripts visible in a code panel you can inspect and edit.

  4. 4

    Run it in your lab. Click Run and the status panel streams results step by step, with measured values inline (VOUT = 3.301 V, asserted 3.2 to 3.4 V, PASS). One click exports a structured PDF report, or the raw results as CSV.

The TestFlow builder: a plain-English request on the left, the generated instrument workflow in the centre, and the live run with its streaming SCPI execution log on the right.
The TestFlow agent turning a plain-English request into a runnable workflow, then running it on the bench. Click to enlarge.
  • Vendor-neutral by design. One workflow drives Keysight, Tektronix, Rohde & Schwarz, NI, Rigol, Keithley, Anritsu, and more over standard VISA and SCPI.
  • Browser-based and shareable. Workflows live in your workspace, so a sequence built in one lab runs the same way in another.
  • Free version to start. Sign in at app.testflowinc.com and build your first workflow today; plans and quotes are on the pricing page.
Instrument vendors TestFlow drives over VISA and SCPI: Keysight, Tektronix, Rohde & Schwarz, NI, Keithley, Agilent, Anritsu, Siglent, Chroma, Fluke, Yokogawa, Kikusui, TDK-Lambda, ESPEC, Watlow, Pickering, Copper Mountain, inTEST, Thermonics, and Microchip
Works with the instruments already on your bench. Full list on the supported instruments page.

The step-by-step walkthrough, VISA address formats, and Test Planner prompts are all in the TestFlow product guide.

Frequently asked questions

What is SCPI?

Standard Commands for Programmable Instruments, a text-based command language for controlling test equipment. It defines a common syntax and a set of required commands, with vendor-specific extensions below the standardised layer.

Are SCPI commands the same across all instruments?

Only partially. The IEEE 488.2 common commands such as *IDN?, *RST, and *CLS are universal. Measurement subsystems are standardised in structure but differ in detail between vendors and even between models from the same vendor.

What does the colon mean in a SCPI command?

It separates levels of the command tree. MEASure:VOLTage:DC? navigates from the MEASure root to VOLTage to DC. A leading colon returns to the root, which matters when chaining commands with semicolons.

What is the difference between MEAS and READ in SCPI?

MEASure configures and triggers a measurement then returns it, the simplest one-shot form. READ triggers and returns using the existing configuration. FETCh returns the last result without triggering. Use CONFigure plus READ when taking many readings with one configuration.

Why do SCPI commands have uppercase and lowercase parts?

The uppercase part is the required short form and the full word is the long form. MEASure means you can send either MEAS or MEASURE. Both are valid and identical, and the short form is faster over slow interfaces.

How do I find the SCPI commands for my instrument?

Use the programming guide for that exact model, not a generic SCPI reference. Vendors publish these as PDFs. The instrument's own error queue, read with SYST:ERR?, is the fastest way to confirm whether a command was accepted.

Ready to automate your lab?

Connect your instruments, describe a test in plain English, and TestFlow builds and runs it in minutes.

Tags

scpi commandsscpi command cheat sheetscpi referencescpi command listinstrument scpi commandsscpi syntax
Share this article:
Ali Kamaly

Article by

Ali Kamaly

Ali Kamaly is the Co-Founder and CEO of TestFlow, an AI-native platform for electronics test automation. He writes about test automation, lab validation, and the infrastructure behind modern hardware engineering.

Put it on your bench this week

A new way for testing, from specs to automated sequences, capture clean data, and accelerate your validation cycle.