HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
ericchiang
pup
HTML2014–2024
ericchiang / pup

pup

Parsing HTML at the command line

27Distinct people
34Mentions
0Explicit recommenders
8.4KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Parsing HTML at the command line

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:03:16 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year34 dated mentions

Observed mentions: 2014-09-13 12:58:43 UTC to 2024-03-20 00:22:58 UTC.

02468102014-01-01 00:00:00 UTC to 2015-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments20142015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 4 mentions; 1 submissions, 3 comments2018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 3 mentions; 2 submissions, 1 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments20192020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 5 mentions; 2 submissions, 3 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 7 mentions; 4 submissions, 3 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 9 mentions; 2 submissions, 7 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2024

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20142014-01-01 00:00:00 UTC2015-01-01 00:00:00 UTC211
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC101
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC211
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC413
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC321
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC000
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC523
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC743
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC927
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC000
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC101

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
pup pup is a command line tool for processing HTML. It reads from stdin, prints to stdout, and allows the user to filter parts of the page using CSS selectors. Inspired by jq, pup aims to be a fast and flexible way of exploring HTML from the terminal. Install Direct downloads are available through the releases page. If you have Go installed on your computer just run go get. go get github.com/ericchiang/pup If you're on OS X, use Homebrew to install (no Go required). brew install https://raw.githubusercontent.com/EricChiang/pup/master/pup.rb Quick start $ curl -s https://news.ycombinator.com/ Ew, HTML. Let's run that through some pup selectors: $ curl -s https://news.ycombinator.com/ | pup 'table table tr:nth-last-of-type(n+2) td.title a' Okay, how about only the links? $ curl -s https://news.ycombinator.com/ | pup 'table table tr:nth-last-of-type(n+2) td.title a attr{href}' Even better, let's grab the titles too: $ curl -s https://news.ycombinator.com/ | pup 'table table tr:nth-last-of-type(n+2) td.title a json{}' Basic Usage $ cat index.html | pup [flags] '[selectors] [display function]' Examples Download a webpage with wget. $ wget http://en.wikipedia.org/wiki/Robots_exclusion_standard -O robots.html Clean and indent By default pup will fill in missing tags and properly indent the page. $ cat robots.html # nasty looking HTML $ cat robots.html | pup --color # cleaned, indented, and colorful HTML Filter by tag $ cat robots.html | pup 'title' <title> Robots exclusion standard - Wikipedia, the free encyclopedia </title> Filter by id $ cat robots.html | pup 'span#See_also' <span class="mw-headline" id="See_also"> See also </span> Filter by attribute $ cat robots.html | pup 'th[scope="row"]' <th scope="row" class="navbox-group"> Exclusion standards </th> <th scope="row" class="navbox-group"> Related marketing topics </th> <th scope="row" class="navbox-group"> Search marketing related topics </th> <th scope="row" class="navbox-group"> Search engine spam </th> <th scope="row" class="navbox-group"> Linking </th> <th scope="row" class="navbox-group"> People </th> <th scope="row" class="navbox-group"> Other </th> Pseudo Classes CSS selectors have a group of specifiers called "pseudo classes" which are pretty cool. pup implements a majority of the relevant ones them. Here are some examples. $ cat robots.html | pup 'a[rel]:empty' <a rel="license" href="//creativecommons.org/licenses/by-sa/3.0/" style="display:none;"> </a> $ cat robots.html | pup ':contains("History")' <span class="toctext"> History </span> <span class="mw-headline" id="History"> History </span> $ cat robots.html | pup ':parent-of([action="edit"])' <span class="wb-langlinks-edit wb-langlinks-link"> <a action="edit" href="//www.wikidata.org/wiki/Q80776#sitelinks-wikipedia" text="Edit links" title="Edit interlanguage links" class="wbc-editpage"> Edit links </a> </span> For a complete list, view the implemented selectors section. +, >, and , These are intermediate characters that declare special instructions. For instance, a comma , allows pup to specify multiple groups of selectors. $ cat robots.html | pup 'title, h1 span[dir="auto"]' <title> Robots exclusion standard - Wikipedia, the free encyclopedia </title> <span dir="auto"> Robots exclusion standard </span> Chain selectors together When combining selectors, the HTML nodes selected by the previous selector will be passed to the next ones. $ cat robots.html | pup 'h1#firstHeading' <h1 id="firstHeading" class="firstHeading" lang="en"> <span dir="auto"> Robots exclusion standard </span> </h1> $ cat robots.html | pup 'h1#firstHeading span' <span dir="auto"> Robots exclusion standard </span> Implemented Selectors For further examples of these selectors head over to MDN. pup '.class' pup '#id' pup 'element' pup 'selector + selector' pup 'selector > selector' pup '[attribute]' pup '[attribute="value"]' pup '[attribute*="value"]' pup '[attribute~="value"]' pup '[attribute^="value"]' pup '[attribute$="value"]' pup ':empty' pup ':first-child' pup ':first-of-type' pup ':last-child' pup ':last-of-type' pup ':only-child' pup ':only-of-type' pup ':contains("text")' pup ':nth-child(n)' pup ':nth-of-type(n)' pup ':nth-last-child(n)' pup ':nth-last-of-type(n)' pup ':not(selector)' pup ':parent-of(selector)' You can mix and match selectors as you wish. cat index.html | pup 'element#id[attribute="value"]:first-of-type' Display Functions Non-HTML selectors which effect the output type are implemented as functions which can be provided as a final argument. text{} Print all text from selected nodes and children in depth first order. $ cat robots.html | pup '.mw-headline text{}' History About the standard Disadvantages Alternatives Examples Nonstandard extensions Crawl-delay directive Allow directive Sitemap Host Universal "*" match Meta tags and headers See also References External links attr{attrkey} Print the values of all attributes with a given key from all selected nodes. $ cat robots.html | pup '.catlinks div attr{id}' mw-normal-catlinks mw-hidden-catlinks json{} Print HTML as JSON. $ cat robots.html | pup 'div#p-namespaces a' <a href="/wiki/Robots_exclusion_standard" title="View the content page [c]" accesskey="c"> Article </a> <a href="/wiki/Talk:Robots_exclusion_standard" title="Discussion about the content page [t]" accesskey="t"> Talk </a> $ cat robots.html | pup 'div#p-namespaces a json{}' [ { "accesskey": "c", "href": "/wiki/Robots_exclusion_standard", "tag": "a", "text": "Article", "title": "View the content page [c]" }, { "accesskey": "t", "href": "/wiki/Talk:Robots_exclusion_standard", "tag": "a", "text": "Talk", "title": "Discussion about the content page [t]" } ] Use the -i / --indent flag to control the intent level. $ cat robots.html | pup -i 4 'div#p-namespaces a json{}' [ { "accesskey": "c", "href": "/wiki/Robots_exclusion_standard", "tag": "a", "text": "Article", "title": "View the con
Read the full README on GitHub

What Hacker News says

34 sources
Unpopular opinion, but Bash/Shell Scripting. Seriously, it's probably the fastest way to get things done. For fetching, use cURL. Want to extract particular markup? Use pup[1]. Want to process csv? Use cskit[2]. Or JSON? Use jq[3]. Want to use DB? Use psql. Once you get the hang of shell scripting, you can create simple scrapers by wiring up these utilities in a matter of minutes. The only thing I wish was present was better support for RegExes. Bash and most unix tools don't support PCRE which can severely limiting. Plus, sometimes you want to process text as a whole vs line-by-line. I would also recommend Python's sh[4] module if Shell scripting isn't your cup of tea. You get best of both worlds: faster dev work with Bash utils, and a saner syntax. [1]: https://github.com/ericchiang/pup [2]: https://csvkit.readthedocs.io/en/latest/ [3]:
Read the rest
In Ask HN: What are the best tools for web scraping in 2022?
Once upon a time I was using pup[0] for such thing as well as later I changed to cascadia[1] which seemed much more advanced. Comparing the two repos, it seems pup is dead, but cascadia may not be. These tools, including htmlq, seem to sell themselves as "jq for html", which is far from the truth. Jq is closer to the awk where you can do just about everything with json. Cascadia, htmlq, and pup seem closer to grep for html. They can essentially only select data from a html source. [0] https://github.com/EricChiang/pup [1] https://github.com/suntong/cascadia
In Htmlq: like jq, but for html

Showing the 15 most recent of 34 sources. Enable JavaScript to search and browse every indexed mention.

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.