npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

open-library-client

v0.1.2

Published

A modern TypeScript API wrapper for the OpenLibrary REST API

Readme

OpenLibrary Client

A modern TypeScript API wrapper for the OpenLibrary REST API, designed to provide a clean and type-safe interface for JavaScript and TypeScript developers.

Features

  • 🚀 Modern TypeScript: Full type safety with comprehensive interfaces and IntelliSense support
  • 📦 Minimal Dependencies: Built with only axios for HTTP requests
  • 🛡️ Error Handling: Robust error handling with detailed typed error responses
  • 🔧 Configurable: Flexible configuration options with type validation
  • 📚 Well Documented: Comprehensive documentation and TypeScript examples
  • 🎯 Focused: Clean API surface focused on essential functionality
  • 💡 Developer Experience: Auto-completion, type checking, and inline documentation

Installation

npm install open-library-client
yarn add open-library-client
pnpm add open-library-client

Quick Start

import { OpenLibraryClient, BookSearchParams, ApiResponse, BookSearchResponse } from 'open-library-client';

// Create a client instance with configuration
const client = new OpenLibraryClient({
  timeout: 15000,
  headers: {
    'User-Agent': 'MyApp/1.0.0'
  }
});

// Search for books with full type safety
const searchParams: BookSearchParams = {
  q: 'The Lord of the Rings',
  author: 'Tolkien',
  limit: 5
};

const results: ApiResponse<BookSearchResponse> = await client.searchBooks(searchParams);

console.log(`Found ${results.data.numFound} books`);
results.data.docs.forEach(book => {
  console.log(`${book.title} by ${book.author_name?.join(', ')}`);
});

Examples

For comprehensive usage examples including complete workflows from search to book details and cover images, see the examples/ folder in the repository.

API Reference

OpenLibraryClient

The main client class for interacting with the OpenLibrary API.

Constructor

new OpenLibraryClient(config?: OpenLibraryClientConfig)

Parameters:

  • config (optional): Configuration options for the client

Configuration Options

interface OpenLibraryClientConfig {
  baseURL?: string;        // Default: 'https://openlibrary.org'
  timeout?: number;        // Default: 10000 (10 seconds)
  headers?: Record<string, string>; // Custom headers
}

Methods

searchBooks(params: BookSearchParams)

Search for books using the OpenLibrary search API.

Parameters:

interface BookSearchParams {
  q: string;                               // Main search query (required)
  title?: string;                          // Search by title
  author?: string;                         // Search by author
  isbn?: string;                           // Search by ISBN
  subject?: string;                        // Search by subject
  limit?: number;                          // Number of results (default: 10, max: 100)
  offset?: number;                         // Pagination offset (default: 0)
  fields?: string;                         // Specific fields to include
  lang?: string;                           // Language preference (e.g., 'en', 'fr', 'es')
  first_publish_year?: number | YearRange; // Filter by first publication year or range
  publish_year?: number | YearRange;       // Filter by any publication year or range
  sort?: SortOption;                       // Sort results by various criteria
}

interface YearRange {
  start: number;    // Start year (inclusive)
  end: number;      // End year (inclusive)
}

type SortOption = 'random' | 'new' | 'old' | 'rating' | 'title' | 'relevance';

Returns:

Promise<ApiResponse<BookSearchResponse>>
getWork(workKey: string)

Get detailed information about a specific work.

Parameters:

  • workKey: The OpenLibrary work key (e.g., "OL45804W")

Returns:

Promise<ApiResponse<WorkDetails>>
getEdition(editionKey: string)

Get detailed information about a specific edition.

Parameters:

  • editionKey: The OpenLibrary edition key (e.g., "OL7353617M")

Returns:

Promise<ApiResponse<EditionDetails>>
getBookByISBN(isbn: string)

Get book information by ISBN.

Parameters:

  • isbn: The ISBN (10 or 13 digits)

Returns:

Promise<ApiResponse<BookDetails>>
getCoverUrl(coverId: number, size?: 'S' | 'M' | 'L')

Generate cover image URL from cover ID.

Parameters:

  • coverId: The cover ID number
  • size: Size of the cover image (default: 'M')

Returns: Cover image URL string

getCoverUrlByISBN(isbn: string, size?: 'S' | 'M' | 'L')

Generate cover image URL from ISBN.

Parameters:

  • isbn: The ISBN (10 or 13 digits)
  • size: Size of the cover image (default: 'M')

Returns: Cover image URL string

Example:

// Basic search with type safety
const basicParams: BookSearchParams = {
  q: 'javascript programming'
};
const results = await client.searchBooks(basicParams);

// Advanced search with multiple parameters
const advancedParams: BookSearchParams = {
  q: 'programming',
  subject: 'javascript',
  limit: 20,
  offset: 0,
  lang: 'en',
  fields: 'key,title,author_name,first_publish_year,isbn'
};
const results = await client.searchBooks(advancedParams);

// Search by specific criteria
const authorParams: BookSearchParams = {
  q: '*',
  author: 'Douglas Crockford',
  title: 'JavaScript'
};
const results = await client.searchBooks(authorParams);

// Random book search with advanced filtering
const randomSciFiParams: BookSearchParams = {
  q: '*',
  subject: 'science fiction',
  first_publish_year: { start: 1980, end: 1989 }, // Books from the 1980s
  sort: 'random',
  limit: 5
};
const randomBooks = await client.searchBooks(randomSciFiParams);

// Random book in specific language
const randomFrenchParams: BookSearchParams = {
  q: '*',
  lang: 'fr',
  sort: 'random',
  limit: 3
};
const frenchBooks = await client.searchBooks(randomFrenchParams);

// Sort by different criteria
const recentBooksParams: BookSearchParams = {
  q: 'programming',
  subject: 'computers',
  sort: 'new',
  limit: 10
};
const recentBooks = await client.searchBooks(recentBooksParams);

// Get detailed work information
const workDetails = await client.getWork("OL45804W");
console.log(workDetails.data.title);
console.log(workDetails.data.description);

// Get specific edition details
const editionDetails = await client.getEdition("OL7353617M");
console.log(editionDetails.data.title);
console.log(editionDetails.data.number_of_pages);

// Get book by ISBN
const bookDetails = await client.getBookByISBN("9780547928227");
console.log(bookDetails.data.title);
console.log(bookDetails.data.publishers);

// Generate cover URLs
const coverUrl = client.getCoverUrl(8739161, 'M');
const coverUrlByISBN = client.getCoverUrlByISBN('9780547928227', 'L');

Response Types

BookSearchResponse

interface BookSearchResponse {
  numFound: number;           // Total number of results found
  start: number;              // Starting position
  numFoundExact: boolean;     // Whether count is exact
  docs: BookSearchResult[];   // Array of book results
  num_found: number;          // Alternative count field
  q: string;                  // Original query
  offset: number | null;      // Current offset
}

BookSearchResult

Each book result contains detailed information:

interface BookSearchResult {
  key: string;                    // OpenLibrary work key
  title: string;                  // Book title
  author_name?: string[];         // Author names
  author_key?: string[];          // Author keys
  first_publish_year?: number;    // First publication year
  publish_year?: number[];        // All publication years
  isbn?: string[];                // ISBN numbers
  publisher?: string[];           // Publishers
  subject?: string[];             // Subjects/topics
  cover_i?: number;               // Cover image ID
  edition_count: number;          // Number of editions
  has_fulltext: boolean;          // Full text available
  // ... and many more fields
}

WorkDetails

Detailed work information:

interface WorkDetails {
  key: string;                    // Work key
  title: string;                  // Work title
  description?: string | object;  // Work description
  authors?: Array<object>;        // Author information
  subjects?: string[];            // Subject classifications
  covers?: number[];              // Cover image IDs
  first_publish_date?: string;    // First publication date
  links?: Array<object>;          // External links
  // ... and more metadata
}

EditionDetails

Detailed edition information:

interface EditionDetails {
  key: string;                    // Edition key
  title: string;                  // Edition title
  subtitle?: string;              // Subtitle
  authors?: Array<object>;        // Author references
  works?: Array<object>;          // Work references
  isbn_10?: string[];             // ISBN-10 numbers
  isbn_13?: string[];             // ISBN-13 numbers
  publishers?: string[];          // Publishers
  publish_date?: string;          // Publication date
  number_of_pages?: number;       // Page count
  physical_format?: string;       // Format (hardcover, paperback, etc.)
  covers?: number[];              // Cover image IDs
  // ... and more edition-specific data
}

BookDetails

Book information (from ISBN lookup):

interface BookDetails {
  key: string;                    // Book key
  title: string;                  // Book title
  subtitle?: string;              // Subtitle
  description?: string | object;  // Description
  authors?: Array<object>;        // Author information
  publishers?: string[];          // Publishers
  publish_date?: string;          // Publication date
  isbn_10?: string[];             // ISBN-10 numbers
  isbn_13?: string[];             // ISBN-13 numbers
  number_of_pages?: number;       // Page count
  covers?: number[];              // Cover image IDs
  subjects?: string[];            // Subjects
  // ... and more book data
}

Error Handling

The client provides structured error handling with TypeScript support:

import { ApiError } from 'open-library-client';

try {
  const searchParams: BookSearchParams = { q: 'test' };
  const results = await client.searchBooks(searchParams);
} catch (error) {
  const apiError = error as ApiError;
  if (apiError.status) {
    console.error(`API Error ${apiError.status}: ${apiError.message}`);
  } else {
    console.error(`Network Error: ${apiError.message}`);
  }
}

Random Book Discovery

The client supports advanced filtering and random sorting for discovering books by various criteria:

Random Books by Genre and Year

// Get random science fiction books from the 1980s
const randomSciFi: BookSearchParams = {
  q: '*',
  subject: 'science fiction',
  first_publish_year: { start: 1980, end: 1989 },
  sort: 'random',
  limit: 5
};
const sciFiBooks = await client.searchBooks(randomSciFi);

Random Books by Language

// Get random books in French
const randomFrench: BookSearchParams = {
  q: '*',
  lang: 'fr',
  sort: 'random',
  limit: 5
};
const frenchBooks = await client.searchBooks(randomFrench);

Sorting Options

// Sort by newest first
const newestBooks: BookSearchParams = {
  q: 'artificial intelligence',
  sort: 'new',
  limit: 10
};

// Sort by highest rated
const topRated: BookSearchParams = {
  q: 'machine learning',
  sort: 'rating',
  limit: 10
};

// Sort alphabetically by title
const alphabetical: BookSearchParams = {
  q: 'data science',
  sort: 'title',
  limit: 10
};

Advanced Usage

Custom Configuration

const client = new OpenLibraryClient({
  timeout: 15000,
  headers: {
    'User-Agent': 'MyApp/1.0.0'
  }
});

Working with Results

const searchParams: BookSearchParams = {
  q: 'artificial intelligence',
  limit: 10
};

const results: ApiResponse<BookSearchResponse> = await client.searchBooks(searchParams);

// Access metadata with full type safety
console.log(`Total results: ${results.data.numFound}`);
console.log(`Showing: ${results.data.docs.length} books`);
console.log(`Response status: ${results.status} ${results.statusText}`);

// Process each book with TypeScript autocompletion
results.data.docs.forEach((book, index) => {
  console.log(`${index + 1}. ${book.title}`);
  
  if (book.author_name?.length) {
    console.log(`   Authors: ${book.author_name.join(', ')}`);
  }
  
  if (book.first_publish_year) {
    console.log(`   First published: ${book.first_publish_year}`);
  }
  
  if (book.cover_i) {
    const coverUrl = `https://covers.openlibrary.org/b/id/${book.cover_i}-M.jpg`;
    console.log(`   Cover: ${coverUrl}`);
  }
  
  if (book.isbn?.length) {
    console.log(`   ISBN: ${book.isbn[0]}`);
  }
});

Pagination

// Get first page with typed parameters
const baseParams: BookSearchParams = {
  q: 'science fiction',
  limit: 10,
  offset: 0
};

let results: ApiResponse<BookSearchResponse> = await client.searchBooks(baseParams);
console.log(`Page 1: ${results.data.docs.length} results`);

// Get second page using spread operator for type safety
const nextPageParams: BookSearchParams = {
  ...baseParams,
  offset: 10
};

results = await client.searchBooks(nextPageParams);
console.log(`Page 2: ${results.data.docs.length} results`);

Development Roadmap

Completed Features:

  • Book Search: Complete search functionality with advanced filtering
  • Work Details: Get detailed information about specific works
  • Edition Data: Access specific edition information
  • Random Discovery: Random book selection with genre, year, and language filtering
  • Cover Images: Generate cover image URLs from cover IDs and ISBNs
  • ISBN Lookup: Direct book lookup by ISBN-10 or ISBN-13

🚧 Future Enhancements:

  • Author Information: Retrieve author details and bibliographies
  • Subject Browsing: Browse books by subject categories
  • Reading Lists: Integration with OpenLibrary reading lists
  • Rate Limiting: Built-in rate limiting for API compliance
  • Caching: Optional response caching for better performance
  • Batch Operations: Support for batch requests

Contributing

This is an open-source project and contributions are welcome! Please see our contributing guidelines for more information.

License

MIT License - see LICENSE file for details.

Links


Built with ❤️ for the JavaScript and TypeScript community.