Search books on Goodreads. Send a keyword such as dune or pride and prejudice, and an optional page. The response is { results, pagination }. Each card has a numeric Goodreads id. Pass that id to /v2/goodreads/book. For Dune the id is 44767458.
Ratings on a search card can be abbreviated. A label such as 1.7 million ratings is stored as 1700000. The book endpoint returns the exact count from the book page.
GET and POST take the same parameters.
GET https://api.piloterr.com/v2/goodreads/search?query=dune
GET https://api.piloterr.com/v2/goodreads/search?query=dune&page=2
GET https://api.piloterr.com/v2/goodreads/search?query=https://www.goodreads.com/search?q=dune&page=2
Page 1 of dune includes 44767458 / Dune by Frank Herbert. pagination.next is https://www.goodreads.com/search?q=dune&page=2. Page 2 uses that URL, reports pagination.page 2, and its book ids do not repeat page 1. Its next is the page 3 Goodreads URL.
| Parameter |
Required |
Example |
query |
yes |
dune |
page |
no |
2 |
query is required. A Goodreads URL must be a search URL. Another host returns 400. page is optional and defaults to 1. It must be an integer of at least 1. When both a search URL and page are sent, page overwrites the page in the URL.
pagination.page is the page Goodreads prints (Page N of M) or, if that label is missing, the page query value. pagination.total_pages is the M from that label, for example 100 on dune. pagination.total_results is null because the search page does not print a result total. pagination.per_page is the number of book cards parsed, 20 on a full dune page.
pagination.next is the Goodreads URL of the Next link, such as https://www.goodreads.com/search?q=dune&page=2. It is null only when that link is absent, which is the last page. Follow next, or send the same keyword with page set to the next number. Ids are unique on a page, and a later page does not repeat them.
| Field |
Type |
Meaning |
results[].id |
string |
Numeric Goodreads book id, such as 44767458 |
results[].title |
string |
Title |
results[].url |
string |
https://www.goodreads.com/book/show/{id} |
results[].series |
string or null |
Series label from the card, such as Dune (Series #1) |
results[].authors |
array of strings |
Author names |
results[].rating |
number or null |
Average rating |
results[].ratings_count |
number or null |
Ratings. Abbreviated labels use the displayed floor, so 1.7 million becomes 1700000 |
results[].reviews_count |
number or null |
Reviews, with the same abbreviation rule |
results[].image |
string or null |
Cover URL |
pagination.page |
integer |
Current page |
pagination.per_page |
integer or null |
Cards on this page |
pagination.total_results |
null |
Not printed |
pagination.total_pages |
integer or null |
Page count Goodreads prints |
pagination.next |
string or null |
Next Goodreads search URL |
The book page for 44767458 uses the same id and title. Its series label can differ slightly (Dune #1 on the book page, Dune (Series #1) on the card) because the two pages print different strings.
- Resolve the title Dune to id
44767458 before reading ISBN, page count, and the exact rating total.
- Walk
pagination.next for dune and collect author names without repeating ids from page 1.
- Compare abbreviated card ratings for
pride and prejudice on page 1, then open the book endpoint for the exact count.
| Code |
Meaning |
400 |
Empty query, a page below 1, or a domain outside goodreads.com |
401 |
Missing API key |
404 |
The page was not a book search |
500 |
The fetch failed |
Goodreads Book