Scrape Goodreads User Data: Profile, Book Shelves, Books, Authors
Project description
Scrape Goodreads User Data: Profile, Book Shelves, Books, Authors
Contents
Usage
Use pipx or uv — both install the CLI from PyPI.
Install once, then run
Best for repeat use. Installs the CLI into an isolated environment and adds the goodreads-user-scraper command to your shell.
pipx install goodreads-user-scraper # or: uv tool install goodreads-user-scraper
goodreads-user-scraper --user_id <your id>
Run once without installing
Best for one-off use. Downloads and runs the CLI in a temporary environment: no install step, no $PATH changes.
pipx run goodreads-user-scraper --user_id <your id>
# or: uvx goodreads-user-scraper --user_id <your id>
Output
Data is written to --output_dir (default goodreads-data/):
goodreads-data/
├── user.json # profile: name, average rating, rating/review counts
└── books/
├── 1420.Hamlet.json # one JSON file per book
└── …
Each books/*.json holds the book's metadata (title, description, genres, page count, cover, ratings) plus your shelves, rating, and dates_read, with the author nested under author. Without a cookie only user.json is written (see Authentication); --skip_authors omits the nested author data.
Arguments
--user_id
- Description: The user whose data should be scraped. Find your user id using these directions.
- Required: Yes
--output_dir
- Description: The directory where all scraped data will be output.
- Required: No
- Default:
goodreads-data
--cookie
- Description: Your Goodreads session cookie (the full
Cookie:request-header value). Required for shelf scraping — see Authentication. - Required: No
- Default: None
--cookie_file
- Description: Path to a text file containing your Goodreads session cookie.
- Required: No
- Default: None
--skip_user_info
- Description: If passed, skip scraping user information.
- Required: No
--skip_shelves
- Description: If passed, skip scraping shelves. Books (and their authors) are scraped from your shelves, so this skips them too.
- Required: No
--skip_authors
- Description: If passed, skip scraping authors.
- Required: No
Authentication
Shelf scraping requires a cookie — Goodreads hides shelf data behind login. Without one you get the profile only; with one you also get shelves, books, and authors.
Getting your session cookie
- Sign in to Goodreads in your browser.
- Open DevTools (Cmd/Ctrl+Shift+I) and switch to the Network tab.
- Refresh the page, then click any
goodreads.comrequest in the list. - In the request Headers, find the
Cookie:header and copy its full value.
Passing the cookie
In order of precedence (first one set wins):
--cookie "<cookie string>"GOODREADS_COOKIEenvironment variable--cookie_file <path-to-file>
Cookies typically last several weeks. If you see a "Cookie appears invalid or expired" error, re-grab the cookie from your browser.
If no cookie is provided, shelf scraping is skipped with a warning. Pass --skip_shelves to suppress the warning.
Troubleshooting
Missing profile or shelf data?
- Your own account: pass your session cookie (see Authentication) — your profile, shelves, and books all scrape, even on a private profile.
- Another user's account: what you can scrape depends on their profile privacy setting. Shelves always require your cookie (see Authentication).
- Anyone: the profile scrapes even without a cookie.
- Goodreads members only: pass your cookie — any signed-in account works.
- Friends only: pass your cookie, and your account must be their friend.
Development
-
Run the install script
bash scripts/install.sh -
Make changes
-
Run the unit tests
pytest
These run against saved Goodreads HTML in
tests/fixtures/— no network, no cookie. This is the CI gate on every push and PR.When Goodreads changes its markup, refresh the fixtures with
scripts/capture_fixtures.py(reads your cookie from.goodreads-cookieif present), then re-runpytest. -
Optionally run the live smoke test
bash scripts/test.shThis scrapes the real Goodreads site end to end. To include shelf scraping, save your Goodreads cookie to a gitignored
.goodreads-cookiefile in the repo root — the test script picks it up automatically. CI runs this monthly (seeintegration.yml) to catch Goodreads markup changes.
Publishing
Publishing is automated via GitHub Actions using PyPI Trusted Publishing (OIDC) — no API tokens are stored.
Run the publish script with the version bump type:
bash scripts/publish.sh <patch|minor|major>
The script bumps the version, creates a git tag, and pushes it. The publish workflow builds the distribution and uploads it to PyPI on any pushed v* tag.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file goodreads_user_scraper-2.3.0.tar.gz.
File metadata
- Download URL: goodreads_user_scraper-2.3.0.tar.gz
- Upload date:
- Size: 15.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1bd1296024731bc7a34d044857fbb15b00fe81668191a2467479b953b06e2db
|
|
| MD5 |
f7e5123242a99bd228112e8ee550884a
|
|
| BLAKE2b-256 |
fcd1b2059add513e03207c89a99e1782529c9b3d9c20d2479d7196ecd1280bd2
|
Provenance
The following attestation bundles were made for goodreads_user_scraper-2.3.0.tar.gz:
Publisher:
publish.yml on YashTotale/goodreads-user-scraper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
goodreads_user_scraper-2.3.0.tar.gz -
Subject digest:
f1bd1296024731bc7a34d044857fbb15b00fe81668191a2467479b953b06e2db - Sigstore transparency entry: 1673282373
- Sigstore integration time:
-
Permalink:
YashTotale/goodreads-user-scraper@dccf28fdb8bd6d66b5b4ca34f9a4e8ffbae61e87 -
Branch / Tag:
refs/tags/v2.3.0 - Owner: https://github.com/YashTotale
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dccf28fdb8bd6d66b5b4ca34f9a4e8ffbae61e87 -
Trigger Event:
push
-
Statement type:
File details
Details for the file goodreads_user_scraper-2.3.0-py3-none-any.whl.
File metadata
- Download URL: goodreads_user_scraper-2.3.0-py3-none-any.whl
- Upload date:
- Size: 12.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6bd721973983ee9fd9365bc5ac4f15b06bf43555dc34c4b6c38a497462444814
|
|
| MD5 |
8327a71c39394c2d7f13e159a848d3ec
|
|
| BLAKE2b-256 |
a9c3e983f2a0c6c3d1194934d65e3bde151f8da86fad89db3aec81653125e4c2
|
Provenance
The following attestation bundles were made for goodreads_user_scraper-2.3.0-py3-none-any.whl:
Publisher:
publish.yml on YashTotale/goodreads-user-scraper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
goodreads_user_scraper-2.3.0-py3-none-any.whl -
Subject digest:
6bd721973983ee9fd9365bc5ac4f15b06bf43555dc34c4b6c38a497462444814 - Sigstore transparency entry: 1673282449
- Sigstore integration time:
-
Permalink:
YashTotale/goodreads-user-scraper@dccf28fdb8bd6d66b5b4ca34f9a4e8ffbae61e87 -
Branch / Tag:
refs/tags/v2.3.0 - Owner: https://github.com/YashTotale
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dccf28fdb8bd6d66b5b4ca34f9a4e8ffbae61e87 -
Trigger Event:
push
-
Statement type: