Skip to content
Latchkey

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

Terminal
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 / functionWhat 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
-nPrint only the number of matches
-pPreserve 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.

Related guides

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