openlibrary

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

openlibrary — Book Metadata from Open Library

openlibrary — Open Library 图书元数据

Query Open Library's 50M+ record catalog over its public HTTP API: search works and authors, walk the edition/work/author graph by ISBN or OLID, enumerate editions, and read community ratings. No API key exists; everything here is a keyless GET.
通过公共 HTTP API 查询 Open Library 超过 5000 万条记录的目录:搜索作品和作者,按 ISBN 或 OLID 遍历版本、作品和作者关系图,枚举版本并读取社区评分。不需要 API key;这里的所有操作都是免密钥 GET。

Setup

初始化

Nothing to authenticate: the public Open Library API requires no API key for reads. There is no token, no registration step, no lazy-auth dance.
bash
undefined
无需身份验证:公共 Open Library API 的读取操作不需要 API key。无需 token、无需注册,也没有延迟认证的繁琐流程。
bash
undefined

Optional etiquette: identified User-Agent gets ~3x rate budget (~3 req/s vs ~1)

Optional etiquette: identified User-Agent gets ~3x rate budget (~3 req/s vs ~1)

export OL_EMAIL="you@example.com"

Requires Python 3.8+ and `requests` only. `--help` and `--dry-run` work with no
environment at all. Write endpoints exist upstream but require an authenticated
Internet Archive session and are effectively internal — treat this surface as
read-only.

Three hosts matter and they serve different things:

| Host | Serves |
|------|--------|
| `openlibrary.org` | metadata JSON: search, records, ratings |
| `covers.openlibrary.org` | cover images + author photos (separate service) |
| `archive.org` | scan content / bulk dumps (redirect targets) |
export OL_EMAIL="you@example.com"

仅需 Python 3.8+ 和 `requests`。`--help` 与 `--dry-run` 在完全没有环境变量的情况下也可运行。上游存在写入端点,但需要经过身份验证的 Internet Archive 会话,实际上属于内部接口——应将此接口视为只读。

有三个重要主机,各自提供不同内容:

| 主机 | 提供 |
|------|--------|
| `openlibrary.org` | 元数据 JSON:搜索、记录、评分 |
| `covers.openlibrary.org` | 封面图片和作者照片(独立服务) |
| `archive.org` | 扫描内容或批量转储(重定向目标) |

Essential Commands

核心命令

find books — search

查找书籍——搜索

bash
openlibrary search --query "dune"                       # relevance order
openlibrary search --query "dune" --sort editions       # most editions first
openlibrary search --query "dune" --sort new            # newest first
openlibrary search --query "foundation" --lang fr       # prefer French editions
openlibrary search --query "dune" --limit 5 --offset 10 # paginate
openlibrary search --query "dune" --json                # machine-readable
Results carry title, authors,
first_publish_year
, edition count, and the work key (
/works/OL…W
) that feeds the other commands. The CLI validates
--sort
choices client-side because an unknown sort value makes the server return a plain-text HTTP 500.
bash
openlibrary search --query "dune"                       # relevance order
openlibrary search --query "dune" --sort editions       # most editions first
openlibrary search --query "dune" --sort new            # newest first
openlibrary search --query "foundation" --lang fr       # prefer French editions
openlibrary search --query "dune" --limit 5 --offset 10 # paginate
openlibrary search --query "dune" --json                # machine-readable
结果包含 title、authors、
first_publish_year
、版本数量,以及可馈入其他命令的 work key(
/works/OL…W
)。CLI 会在客户端验证
--sort
选项,因为未知排序值会让服务器返回纯文本 HTTP 500。

find people who write — author search

查找作者——作者搜索

bash
openlibrary search-authors --query "asimov"             # name candidates
openlibrary search-authors --query "le guin" --limit 5
openlibrary search-authors --query "asimov" --json      # includes top_work, work_count
Author docs arrive with bare keys (
OL23919A
), unlike book search's path keys.
bash
openlibrary search-authors --query "asimov"             # name candidates
openlibrary search-authors --query "le guin" --limit 5
openlibrary search-authors --query "asimov" --json      # includes top_work, work_count
作者文档返回裸键(
OL23919A
),不同于书籍搜索返回的路径键。

inspect records — author / work

查看记录——作者或作品

bash
openlibrary author OL23919A                # bio, dates, photo URL
openlibrary work OL1168083W                # description, subjects, cover URL
openlibrary work OL1168083W --json         # full record
Keys may be passed bare (
OL23919A
) or as paths (
/authors/OL23919A
) — the CLI normalizes both.
bash
openlibrary author OL23919A                # bio, dates, photo URL
openlibrary work OL1168083W                # description, subjects, cover URL
openlibrary work OL1168083W --json         # full record
键可以以裸形式(
OL23919A
)或路径形式(
/authors/OL23919A
)传入——CLI 会将二者标准化。

resolve an ISBN

解析 ISBN

bash
openlibrary isbn 9780451524935             # ISBN-10 or ISBN-13
openlibrary isbn 9780451524935 --json      # + resolved edition_key, work_keys, cover_url
Upstream,
/isbn/<isbn>.json
answers a 302 redirect to the canonical edition JSON (
/books/<OL…M>.json
). The CLI follows it and reports which edition matched via
edition_key
. If the edition record lacks author names (some ship
authors:null
), the CLI recovers them from the linked work.
bash
openlibrary isbn 9780451524935             # ISBN-10 or ISBN-13
openlibrary isbn 9780451524935 --json      # + resolved edition_key, work_keys, cover_url
在上游,
/isbn/<isbn>.json
会对规范 edition JSON(
/books/<OL…M>.json
)返回 302 redirect。CLI 会跟随该重定向,并通过
edition_key
报告匹配到的版本。如果版本记录缺少作者姓名(有些记录返回
authors:null
),CLI 会从关联的 work 中恢复这些姓名。

list every edition of a work

列出作品的所有版本

bash
openlibrary editions OL81699W                          # publisher/date/ISBN per edition
openlibrary editions OL81699W --limit 50 --offset 50   # page through large sets
openlibrary editions OL81699W --json                   # + next_offset when more exist
Backs onto
/works/<key>/editions.json
;
next_offset
is computed from the server's prebuilt next-page link.
bash
openlibrary editions OL81699W                          # publisher/date/ISBN per edition
openlibrary editions OL81699W --limit 50 --offset 50   # page through large sets
openlibrary editions OL81699W --json                   # + next_offset when more exist
该命令基于
/works/<key>/editions.json
;
next_offset
根据服务器预生成的下一页链接计算。

read the room — community signals

了解社区动向——社区信号

bash
openlibrary ratings OL45804W               # average rating + shelf counts
openlibrary ratings OL45804W --json        # full distribution + bookshelves
Joins
/works/<key>/ratings.json
(
summary.average
, per-star
counts
) with
/works/<key>/bookshelves.json
(
want_to_read
,
currently_reading
,
already_read
).
bash
openlibrary ratings OL45804W               # average rating + shelf counts
openlibrary ratings OL45804W --json        # full distribution + bookshelves
该命令合并
/works/<key>/ratings.json
(
summary.average
、逐星
counts
)与
/works/<key>/bookshelves.json
(
want_to_read
、
currently_reading
、
already_read
)。

Global Flags

全局标志

Position-independent; put them before or after the subcommand:
bash
openlibrary --json search --query "dune"     # machine output anywhere
openlibrary --dry-run isbn 9780451524935     # preview the exact URL, no network
openlibrary --quiet search --query "dune"    # suppress diagnostics
FlagEffect
--json
One JSON object on stdout instead of human text
--dry-run
Print the planned request as JSON without executing it
--quiet
Suppress non-essential output
--verbose
Verbose logging
与位置无关;可放在子命令之前或之后:
bash
openlibrary --json search --query "dune"     # machine output anywhere
openlibrary --dry-run isbn 9780451524935     # preview the exact URL, no network
openlibrary --quiet search --query "dune"    # suppress diagnostics
标志效果
--json
在 stdout 上输出单个 JSON 对象,而不是人类可读文本
--dry-run
以 JSON 打印计划执行的请求,但不实际执行
--quiet
抑制非必要输出
--verbose
输出详细日志

Multi-Step Pipeline Recipes

多步骤管道示例

ISBN → edition → work → author bio

ISBN → edition → work → 作者简介

The canonical walk across all three key types:
bash
openlibrary isbn 9780451524935 --json | jq -r '.work_keys[0]'   # OL1168083W
openlibrary work OL1168083W --json | jq -r '.authors[0]'        # bare OL…A key
openlibrary author OL118077A                                    # bio, dates
The CLI keeps this pipeline type-safe: every command that emits an
authors
field under
--json
(
isbn
,
work
) uses the same shape — an array of bare OL…A keys — while human output renders comma-separated labels instead. Each hop uses a different key suffix (M → W → A); see Known Gotchas before hand-assembling these URLs yourself.
这是跨越三种键类型的标准遍历链路:
bash
openlibrary isbn 9780451524935 --json | jq -r '.work_keys[0]'   # OL1168083W
openlibrary work OL1168083W --json | jq -r '.authors[0]'        # bare OL…A key
openlibrary author OL118077A                                    # bio, dates
CLI 让这条管道保持类型安全:在
--json
下输出
authors
字段的每个命令(
isbn
、
work
)都使用相同结构——由裸 OL…A 键组成的数组——而人类可读输出则改为显示逗号分隔的标签。每一跳使用不同的键后缀(M → W → A);在手动拼接这些 URL 前,请先参阅“常见陷阱”。

Rank a series by community love

按社区喜爱度为系列排名

bash
for w in $(openlibrary search --query 'series:dune' --limit 8 --json | jq -r '.results[].key'); do
  openlibrary ratings "${w##*/}" --json \
    | jq -c '{work: .key, avg: .average, rated: .ratings_count,
              want_to_read: .bookshelves.want_to_read}'
done
bash
for w in $(openlibrary search --query 'series:dune' --limit 8 --json | jq -r '.results[].key'); do
  openlibrary ratings "${w##*/}" --json \
    | jq -c '{work: .key, avg: .average, rated: .ratings_count,
              want_to_read: .bookshelves.want_to_read}'
done

Find readable ebooks, then their print editions

查找可读电子书及其纸质版本

bash
openlibrary search --query 'title:"moby dick"' --sort editions --json \
  | jq '.results[] | select(.has_fulltext) | {title, key}'
openlibrary editions OL81699W --json | jq '.editions[] | {key, isbn_13}'
bash
openlibrary search --query 'title:"moby dick"' --sort editions --json \
  | jq '.results[] | select(.has_fulltext) | {title, key}'
openlibrary editions OL81699W --json | jq '.editions[] | {key, isbn_13}'

Using --json with jq

将
--json
与
jq
配合使用

bash
openlibrary search --query "voracious" --json | jq '.results[] | {title, first_publish_year}'
openlibrary search-authors --query "butler" --json | jq '.results[0] | {name, key, top_work}'
openlibrary isbn 9780451524935 --json | jq -r '.cover_url'          # covers host URL
openlibrary editions OL81699W --json | jq '[.editions[].publish_date]'
openlibrary ratings OL45804W --json | jq '.rating_distribution'
bash
openlibrary search --query "voracious" --json | jq '.results[] | {title, first_publish_year}'
openlibrary search-authors --query "butler" --json | jq '.results[0] | {name, key, top_work}'
openlibrary isbn 9780451524935 --json | jq -r '.cover_url'          # covers host URL
openlibrary editions OL81699W --json | jq '[.editions[].publish_date]'
openlibrary ratings OL45804W --json | jq '.rating_distribution'

Known Gotchas

常见陷阱

  • ISBN endpoints answer 302, not JSON —
    /isbn/<isbn>.json
    ,
    /lccn/*.json
    ,
    /oclc/*.json
    redirect to
    /books/<OL…M>.json
    . Clients must follow redirects (
    curl -L
    ;
    requests
    does by default) or they parse an HTML redirect page. Direct
    /books/<OLID>.json
    calls return 200 immediately.
  • Merged keys return redirect stubs inside HTTP 200 — Open Library is a wiki; when duplicate works merge, the old key keeps answering 200 with
    {"type":{"key":"/type/redirect"},"location":"/works/<master>"}
    instead of a 3xx. Detect the stub type in success responses and re-fetch. The bundled CLI does this automatically (and appends
    .json
    to stub locations, since extension-less URLs redirect to HTML pages).
  • Key types are encoded in the suffix —
    OL…M
    = edition (
    /books/
    ),
    OL…W
    = work (
    /works/
    ),
    OL…A
    = author (
    /authors/
    ). Works link to authors double-nested (
    authors[].author.key
    ); editions nest flat (
    authors[].key
    ) — or ship
    authors:null
    entirely, recovering names from the linked work. Requesting a key under the wrong collection yields a 301 reroute.
  • Search empties are not errors — malformed queries parse loosely and come back HTTP 200 with
    numFound:0
    ; conversely a bad
    sort=
    enum is a plain-text HTTP 500 and non-integer
    limit
    is a FastAPI 422. Branch on bodies, not just status codes.
  • availability
    needs
    ia
    — in raw
    /search.json
    calls, requesting
    fields=availability
    silently returns nothing unless
    ia
    is also requested.
  • Covers live on another host — image URLs are always
    covers.openlibrary.org/b/id/<cover_id>-{S,M,L}.jpg
    (or
    /b/isbn/...
    ,
    /a/id/...
    for author photos). Missing covers return a blank placeholder with HTTP 200 unless you add
    ?default=false
    ; non-ID/non-OLID lookups cap at 100 req/IP per 5 min then 403; cover URLs often 302 into archive.org zip shards.
  • Rate limits are policy, not headers — no Retry-After/X-Rate-Limit headers exist. Anonymous ≈1 req/s; a
    User-Agent: App (email)
    (set
    OL_EMAIL
    ) raises it to ≈3 req/s. Batch with one search rather than hundreds of lookups; bulk belongs in monthly dumps.
  • Text fields nest
    {type,value}
    objects
    — older records wrap
    bio
    ,
    description
    ,
    notes
    as
    {"type":"/type/text","value":"..."}
    while newer ones use plain strings. Handle both; the CLI unwraps centrally.
  • OLID ≠ long-term identity — deleted keys can be reassigned to unrelated books, and merged-away keys become redirect stubs. Pair OLIDs with title/ISBN in any cache.
  • .json
    placement matters for slugged URLs
    — append
    .json
    to the bare key (
    /authors/OL23919A.json
    ), never after a slug path.
  • ISBN 端点返回 302,而不是 JSON —
    /isbn/<isbn>.json
    、
    /lccn/*.json
    、
    /oclc/*.json
    会重定向到
    /books/<OL…M>.json
    。客户端必须跟随重定向(
    curl -L
    ;
    requests
    默认会跟随),否则解析到的将是 HTML 重定向页面。直接调用
    /books/<OLID>.json
    会立即返回 200。
  • 合并键会在 HTTP 200 响应中返回重定向存根 — Open Library 是一个 wiki;当重复作品被合并时,旧键仍会返回 HTTP 200,响应内容为
    {"type":{"key":"/type/redirect"},"location":"/works/<master>"}
    ,而不是 3xx。应在成功响应中检测这种存根类型并重新请求。内置 CLI 会自动处理这一点(并为存根位置追加
    .json
    ,因为无扩展名 URL 会重定向到 HTML 页面)。
  • 键类型编码在后缀中 —
    OL…M
    = edition(
    /books/
    ),
    OL…W
    = work(
    /works/
    ),
    OL…A
    = author(
    /authors/
    )。works 通过双层嵌套关联 authors(
    authors[].author.key
    );editions 采用扁平嵌套(
    authors[].key
    )——或者完全不返回
    authors:null
    ,此时从关联 work 恢复姓名。在错误的 collection 下请求键会收到 301 reroute。
  • 搜索结果为空并不是错误 — 查询格式错误时解析较宽松,服务器会返回 HTTP 200 且
    numFound:0
    ;反过来,错误的
    sort=
    枚举值会返回纯文本 HTTP 500,非整数
    limit
    则会触发 FastAPI 422。应依据响应体分支处理,而不能只看状态码。
  • availability
    需要
    ia
    — 在原始
    /search.json
    调用中,除非同时请求
    ia
    ,否则请求
    fields=availability
    会静默返回空值。
  • 封面位于另一台主机 — 图片 URL 始终为
    covers.openlibrary.org/b/id/<cover_id>-{S,M,L}.jpg
    (作者照片则使用
    /a/id/...
    )。缺少封面时,除非添加
    ?default=false
    ,否则会返回 HTTP 200 的空白占位图;非 ID、非 OLID 查询每 IP 每 5 分钟最多 100 次,随后返回 403;封面 URL 通常会 302 重定向到 archive.org zip 分片。
  • 速率限制是策略而非响应头 — 不存在 Retry-After 或 X-Rate-Limit 响应头。匿名访问约为 1 req/s;设置
    User-Agent: App (email)
    (即设置
    OL_EMAIL
    )后提升至约 3 req/s。批量操作应使用单次搜索,而不是执行数百次查找;批量数据应使用每月转储。
  • 文本字段会嵌套为
    {type,value}
    对象
    — 较旧记录将
    bio
    、
    description
    、
    notes
    包装为
    {"type":"/type/text","value":"..."}
    ,较新记录则使用普通字符串。应同时处理两种形式;CLI 会在统一位置解包。
  • OLID ≠ 长期身份标识 — 已删除的键可能被重新分配给无关书籍,被合并掉的键则变成重定向存根。在任何缓存中,都应将 OLID 与 title/ISBN 配对使用。
  • 带 slug 的 URL 中
    .json
    的位置很重要
    — 应将
    .json
    追加到裸键末尾(
    /authors/OL23919A.json
    ),绝不要追加在 slug 路径之后。

When to use

适用场景

  • Any question about books, authors, or works Open Library's public catalog can answer
  • Resolving ISBNs/OLID keys to canonical records and walking edition/work/author graphs
  • Finding readable or borrowable scans, cover images, community ratings/shelf counts
  • Open Library 公共目录能回答的任何书籍、作者或作品问题
  • 将 ISBN/OLID 键解析为规范记录,并遍历版本、作品和作者关系图
  • 查找可阅读或可借阅的扫描件、封面图片、社区评分及书架数量

When not to use

不适用场景

Do not use this skill for local library-catalog administration — Koha/Evergreen ILS configuration, MARC batch processing, patron management — or for licensed commercial data feeds (ISBNdb, Google Books), citation formatting, or managing your own Open Library reading account/lists (that requires site login this skill deliberately does not handle). For movie/TV metadata use tmdb instead.
不要将此 skill 用于本地图书馆目录管理——Koha/Evergreen ILS 配置、MARC 批量处理、读者管理——也不用于授权的商业数据源(ISBNdb、Google Books)、引文格式化,或管理你自己的 Open Library 阅读账户或列表(这些操作需要站点登录,而此 skill 有意不予处理)。对于电影或电视元数据,请改用 tmdb。

Reference Files

参考文件

FileTopicRead when
references/api-overview-and-key-graph.mdAccess model, rate-limit etiquette, OLID M/W/A key graph, cross-collection 301s, merge-stub handling,
{type,value}
text wrapping
Assembling record URLs by hand, handling merges/wrong-key errors, or planning request pacing
references/search-api-guide.md
/search.json
parameters, sort keys, field scopes (
title:
,
isbn:
, …),
fields=
projection incl. the availability/ia interaction,
/search/authors.json
,
/subjects/<name>.json
, inside-book search, error model
Building precise queries, paginating deep result sets, or debugging empty results
references/books-isbn-and-covers.mdIdentifier endpoints and their 302 resolution, raw records vs legacy
/api/books
view models, editions listing, ratings/bookshelves shapes, covers-host URL rules and limits
Working with ISBNs/LCCNs/OCLCs, enumerating editions, or fetching images
references/recipes-and-gotchas.mdEnd-to-end curl/jq pipelines (ISBN→work→author chain, ebook discovery, cover assembly, disambiguation) plus a symptom-indexed gotcha tableWiring multi-step workflows or diagnosing an unexpected response
文件主题阅读时机
references/api-overview-and-key-graph.md访问模型、速率限制礼仪、OLID M/W/A 键图、跨 collection 301、合并存根处理、
{type,value}
文本包装
手动组装记录 URL、处理合并或错误键,或规划请求节奏时
references/search-api-guide.md
/search.json
参数、排序键、字段作用域(
title:
、
isbn:
等)、
fields=
投影(包括 availability/ia 交互)、
/search/authors.json
、
/subjects/<name>.json
、书内搜索、错误模型
构建精确查询、深层分页,或调试空结果时
references/books-isbn-and-covers.md标识符端点及其 302 解析、原始记录与旧版
/api/books
视图模型、版本列表、评分与书架结构、封面主机 URL 规则和限制
处理 ISBN/LCCN/OCLC、枚举版本或获取图片时
references/recipes-and-gotchas.md端到端 curl/jq 管道(ISBN→work→author 链、电子书发现、封面组装、消歧),以及按症状索引的陷阱表连接多步骤工作流或诊断异常响应时

Available Scripts

可用脚本

ScriptPurposeInvocation
scripts/openlibrary
The CLI this skill drives:
search
,
search-authors
,
author
,
work
,
isbn
,
editions
,
ratings
— all with
--json
/
--dry-run
, automatic 302 + merge-stub resolution,
{type,value}
unwrapping, covers-host URL assembly, and client-side sort validation. Run it for every book-metadata question above.
scripts/openlibrary search --query "dune" --json
scripts/test_openlibrary.py
Offline pytest/unittest suite covering help, argument errors, dry-run plans, mocked-client logic (redirect stubs, author fallback, editions paging), plus two env-guarded live probes (
OPENLIBRARY_LIVE_TESTS=1
). Zero egress otherwise.
.venv/bin/python3 -m pytest -p no:cacheprovider --strict-markers scripts/test_openlibrary.py
脚本用途调用方式
scripts/openlibrary
此 skill 驱动的 CLI:
search
、
search-authors
、
author
、
work
、
isbn
、
editions
、
ratings
——全部支持
--json
/
--dry-run
,并自动处理 302 与合并存根解析、
{type,value}
解包、封面主机 URL 组装和客户端排序校验。对于上述每个图书元数据问题,都应运行该脚本。
scripts/openlibrary search --query "dune" --json
scripts/test_openlibrary.py
离线 pytest/unittest 测试套件,覆盖帮助信息、参数错误、dry-run 计划、mock client 逻辑(重定向存根、作者回退、版本分页),以及两个受环境变量保护的真实探测(
OPENLIBRARY_LIVE_TESTS=1
)。默认不产生网络请求。
.venv/bin/python3 -m pytest -p no:cacheprovider --strict-markers scripts/test_openlibrary.py

Prerequisites

前置条件

  • Python 3.8+ with
    requests
    (stdlib otherwise); invoke as
    python3 scripts/openlibrary ...
    if not executable directly
  • No credentials of any kind; optional
    OL_EMAIL
    for rate-limit etiquette
  • jq
    recommended for
    --json
    post-processing
  • Python 3.8+ 和
    requests
    (其余均使用标准库);如果脚本未直接设为可执行文件,请使用
    python3 scripts/openlibrary ...
    调用
  • 无需任何凭据;可选用
    OL_EMAIL
    遵守速率限制礼仪
  • 推荐使用
    jq
    对
    --json
    输出进行后处理