Skip to content
Latchkey

pup: Parse HTML on the Command Line

pup filters HTML from stdin with CSS selectors and display functions, including text{}, attr{href} and json{} for structured output.

pup is the established command-line HTML processor, modeled on jq. You chain CSS selectors, then a display function decides what to print.

What it does

pup takes HTML on stdin, applies a CSS selector chain, and prints the result. A trailing display function changes the form: text{} for inner text, attr{href} for an attribute, and json{} for a JSON tree you can pipe into jq.

Common usage

Terminal
# text of the first h1
curl -s https://example.com | pup 'h1 text{}'
# every link href
curl -s https://example.com | pup 'a attr{href}'
# emit JSON for jq to consume
curl -s https://example.com | pup 'table json{}' | jq '.'

Options

Selector / functionWhat it does
text{}Print the combined inner text of matches
attr{name}Print the value of an attribute
json{}Emit matches as a JSON structure
slice{a:b}Keep a subrange of the matched nodes
-n, --numberPrint the number of matches
-f, --file <file>Read HTML from a file
-c, --colorColorize output

In CI

Use pup ... json{} to turn a scraped HTML table into JSON and then assert on it with jq, bridging an HTML source into a JSON-based test. For a quick existence check, pup "selector" -n prints the match count you can compare against an expected value.

Common errors in CI

pup: command not found: install via go install github.com/ericchiang/pup@latest or a release binary. An unmatched selector yields empty output with exit 0, so guard checks against blank results. A malformed selector prints Failed to parse selector to stderr and exits non-zero. Like htmlq, pup reads stdin, so a forgotten pipe just hangs waiting on input.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →