HomeThe Stash

SPL Cheat Sheet: Splunk Search Processing Language

ReferenceSeptember 19, 2026

ReferenceSplunk SPLLast verified Sep 2026Copy-paste queries

SPL — Search Processing Language — is how you ask Splunk questions. A search reads left to right, piping results from one command into the next with |. Learn the dozen commands here and you can investigate in any Splunk-based SOC. Want a Splunk to run these against? Stand one up free with the Splunk Docker lab.

Almost every search has the same shape: pick the data, filter it down, then transform it into a number or a table. Get that rhythm and the rest is vocabulary.

The shape of every search

Start by choosing an index and sourcetype, then pipe into commands. Filtering terms go right after the search, before the first pipe — that is what keeps a search fast.

index=main sourcetype=access_combined status=500

Pick data and filter in one step: the main index, web access logs, only HTTP 500s. Bare terms after the search are ANDed together.

index=main sourcetype=access_combined status=500
| stats count by clientip
| sort - count

The full arc — pick, filter, transform, order. Each | hands its results to the next command. This counts 500s per client IP, worst first.

Filter and choose fields

Command What it does Example
search Add more filters mid-pipeline ... | search status>=400
where Filter with expressions and functions ... | where bytes > 1000000
fields Keep or drop fields (keep speeds things up) ... | fields clientip, status
dedup Remove duplicate events by a field ... | dedup user
sort Order results; a − means descending ... | sort - count
head / tail Keep the first / last N results ... | head 20

Turn events into numbers

These transforming commands are where investigation happens — they collapse thousands of events into a count, a trend, or a table.

Command What it does Example
stats Aggregate: count, sum, avg, values, dc (distinct count) ... | stats count by user
count The workhorse metric, often with by ... | stats count by src, dest
timechart stats over time — draws a trend ... | timechart span=1h count
chart stats split across two dimensions ... | chart count over status by host
top The most common values of a field ... | top limit=10 uri_path
rare The least common values — great for outliers ... | rare process_name
index=main sourcetype=access_combined
| timechart span=15m count by status

A classic dashboard query: request volume every 15 minutes, split by HTTP status. A spike of 401s or 500s jumps out immediately.

Compute and reshape

Command What it does Example
eval Create or modify a field with an expression ... | eval mb=round(bytes/1024/1024,2)
if / case Conditional values inside eval ... | eval risk=if(status=200,"ok","check")
rename Give a field a readable name ... | rename clientip AS "Source IP"
table Pick exact columns, in order, as a table ... | table _time, user, action
fillnull Replace missing values ... | fillnull value=0 count

Extract and enrich

Real data is messy. rex pulls fields out of raw text with a regex; lookups join your events to reference tables (asset owners, threat lists, geolocation).

index=main sourcetype=syslog
| rex field=_raw "user=(?<username>\w+)"
| stats count by username

Extract a username field from raw syslog with a named capture group, then count by it. Named groups (?<name>...) become fields.

index=main sourcetype=firewall
| lookup threat_ips ip AS src_ip OUTPUT threat_level
| where isnotnull(threat_level)

Join firewall events to a threat_ips lookup table on the IP, pull in a threat_level, and keep only the matches. This is how watchlists become alerts.

SOC searches you’ll actually run

Copy these, change the index and field names to match your data, and go:

index=* (EventCode=4625 OR "authentication failure")
| stats count by user, src
| where count > 5
| sort - count

Brute-force detection — users with more than five failed logins from a source. Windows logs failed auth as EventCode 4625; Linux says “authentication failure”.

index=* sourcetype=WinEventLog:Security EventCode=4624
| stats dc(ComputerName) AS hosts values(ComputerName) by user
| where hosts > 3

Lateral movement hint — one account logging in successfully (4624) to more than three hosts in the window. dc() is distinct count.

index=* sourcetype=firewall action=allowed
| stats sum(bytes_out) AS total by src_ip
| sort - total
| head 10

Top talkers / possible exfiltration — the ten internal IPs sending the most data out. A quiet host suddenly at the top is worth a look.

index=* sourcetype=sysmon EventCode=1
| rare limit=20 Image

Rare process hunt — the least-common executables launched (Sysmon EventCode 1). Malware and living-off-the-land tools often surface here.

Speed and gotchas

  • Filter early, filter hard. Always name an index= and sourcetype=, and put keyword filters before the first pipe.
  • Avoid leading wildcards. *error forces a full scan; error* is fine.
  • Use fields early to drop what you don’t need — less data down the pipe is faster.
  • For huge datasets, learn tstats — it queries indexed metadata and is dramatically faster than stats on raw events.
  • Pick a real time range. “All time” is the most common reason a search crawls.

Where to go next

A working analyst’s SPL starter kit, verified Sep 2026. SPL is stable, but if a command’s changed or you want one added, tell me.