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
# 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 / function | What 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, --number | Print the number of matches |
| -f, --file <file> | Read HTML from a file |
| -c, --color | Colorize 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.