Skip to content
goodread

Quick start

From an empty terminal to a real book, a real work, a real edition list and a local graph you can query, in a handful of commands.

This walks the core loop: read a book, read the work behind it, list its editions, build a small local store and query it offline. Everything here is on a surface robots.txt allows, so nothing needs a flag.

1. Read a book

goodread book 2767052
The Hunger Games (The Hunger Games, #1)
by Suzanne Collins

id          2767052
work        2792775
series      The Hunger Games #1
published   2008-10-14
publisher   Scholastic Press
format      Hardcover
pages       374
language    English
isbn13      9780439023481
url         https://www.goodreads.com/book/show/2767052-the-hunger-games

4.35 average from 10,233,344 ratings, 275,272 text reviews

book takes a bare id, a full URL, or several at once. The same record as JSON:

goodread book 2767052 --json

That JSON carries more than the table shows: surfaces says which pages it was read from, via and level say which rung of the extraction ladder answered for each field, and missed is a list of plain sentences about what this page did not carry.

2. Read the work behind it

The book above is one printing. The work is the thing Suzanne Collins wrote:

goodread work 2792775

/work/<id> is disallowed by robots.txt, so work reads the editions page and then the first edition's own page, which carries the work with its places, characters and awards. That costs two requests, and the record says which edition it came through.

3. List the editions

goodread editions 2792775

One row per printing, and this is where the ISBNs are. A work does not have an ISBN and a book has only its own, so if you want them all, this is the command. Pages are explicit:

goodread editions 2792775 --page 2 --pages 3

4. Resolve an identifier

If what you have is an ISBN rather than an id:

goodread lookup 9780439023481
goodread lookup "the hunger games"

lookup goes through the open autocomplete route, which needs no key and is allowed.

5. Classify without fetching

id turns a URL or id into an (entity, id) pair without touching the network, which is handy in scripts:

goodread id https://www.goodreads.com/book/show/2767052
book	2767052

6. Build a small store and query it

Everything read can be folded into a local SQLite graph. Look before you leap:

goodread crawl --seed gr:author/153394 --depth 1 --dry-run

--dry-run prints the plan and reads nothing, which is how you find out a crawl is twelve hours before starting it. Drop the flag to run it:

goodread crawl --seed gr:author/153394 --depth 1

Then work offline:

goodread find hunger
goodread graph gr:book/2767052 --depth 2
goodread query "select title, isbn13, num_pages from books order by num_pages desc limit 5"
goodread export --to jsonl > books.jsonl

An interrupted crawl continues where it stopped when you run the same command again, because the frontier lives in the store.

7. Compose

Output that pipes is the point. The default is a table on a terminal and JSONL when piped, so the same command reads well by hand and parses cleanly in a pipe:

goodread editions 2792775 | jq -r .isbn13
goodread book 2767052 --fields title,isbn13,num_pages -f tsv
goodread book 2767052 --template '{{.Book.Title}} isbn {{.Book.ISBN13}}'

Where to next

You have the core loop. From here: