pup: HTML Processing With CSS Selectors
pup takes HTML on stdin and a CSS selector, then prints the matched HTML or, with a display function like text{} or json{}, just the text, an attribute, or a JSON tree.
pup is a fast Go tool for slicing HTML in pipelines. Its display functions (text{}, attr{href}, json{}) turn a selection into exactly the shape a later step needs. This page covers pipeline usage; the base reference is pup-html-parse.
What it does
pup parses HTML from stdin, applies the CSS selector, and by default prints the matched HTML. Append a display function to reshape it: text{} for text content, attr{href} for an attribute, or json{} to emit the selection as JSON for jq.
Common usage
curl -s https://example.com | pup 'h1 text{}'
curl -s https://example.com | pup 'a.download attr{href}'
# emit JSON and hand off to jq
curl -s https://example.com | pup 'table json{}' | jq '.[0]'Options
| Selector / function | What it does |
|---|---|
| text{} | Print the text content of the selection |
| attr{name} | Print the value of the named attribute |
| json{} | Emit the selection as a JSON tree |
| -n | Print only the number of matches |
| -p | Preserve original whitespace/formatting |
In CI
pup json{} is the bridge to jq when the value lives in structured markup: pup 'table json{}' | jq .... For a single value, attr{href} or text{} is enough. As with htmlq, a selector matching nothing yields empty output and exit 0, so assert non-empty when a value is required to fail the build on absence.
Common errors in CI
"Selector parse error" (pup prints an error and exits non-zero) means a malformed selector or an unsupported pseudo-class. An empty result is a no-match, not an error, so test the output length. json{} on a large document can be big; narrow the selector before piping to jq. JavaScript-rendered content is not present in the static HTML pup sees.