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

audible-core

v1.0.0

Published

TypeScript library for Audible API authentication and library management

Readme

audible-core

A TypeScript library for Audible API authentication and library management. Provides both Node.js and browser-compatible builds for building Audible-integrated applications.

Features

  • Complete authentication flow - OAuth URL generation, device registration, token management
  • Library management - Fetch audiobooks, get download URLs, retrieve activation bytes
  • Browser support - Subset of functions work in browser environments (React, Vue, etc.)
  • CAPTCHA reduction - Special cookie generation reduces CAPTCHA frequency by ~80%
  • TypeScript native - Full type definitions included
  • Well tested - 34 tests covering all functionality

Installation

npm install audible-core

For local development:

# In audible-core directory
npm link

# In your project
npm link audible-core

Quick Start

Node.js - Complete Flow

import {
  generateAuthUrl,
  parseCallbackUrl,
  registerDevice,
  Authenticator,
  AudibleClient,
  getLibrary,
} from 'audible-core';

// 1. Generate auth URL
const { url, codeVerifier, serial, instructions } = generateAuthUrl('us');
console.log(instructions); // Show user what to expect
console.log(url); // User visits this URL

// 2. User logs in, gets redirected to error page, copies URL
const callbackUrl = '...'; // User provides this

// 3. Extract authorization code
const { authorizationCode } = parseCallbackUrl(callbackUrl);

// 4. Register device and get credentials
const credentials = await registerDevice({
  authorizationCode,
  codeVerifier,
  serial,
  localeCode: 'us',
});

// 5. Use credentials to access API
const authenticator = new Authenticator(credentials);
const client = new AudibleClient(authenticator, 'us');
const library = await getLibrary(client);

console.log(`Found ${library.length} audiobooks`);

Browser (React) - Auth Flow Only

import {
  generateAuthUrl,
  buildInitCookies,
  validateCallbackUrl,
} from 'audible-core/browser';

function AudibleConnect() {
  const handleConnect = () => {
    // Generate OAuth URL with helpful instructions
    const { url, instructions, expectedRedirectDomain } = generateAuthUrl('us');

    // Generate cookies that reduce CAPTCHA frequency
    const cookies = buildInitCookies();
    console.log('Set these cookies before opening URL:', cookies);

    // Open auth URL in new window
    window.open(url, '_blank');

    // Show instructions to user
    alert(instructions);
  };

  const handleUrlPaste = (pastedUrl: string) => {
    // Validate URL and extract auth code
    const result = validateCallbackUrl(pastedUrl);

    if (result.valid) {
      // Send to your server proxy for device registration
      fetch('/api/audible/register', {
        method: 'POST',
        body: JSON.stringify({ code: result.authorizationCode }),
      });
    } else {
      alert(result.error);
    }
  };

  return (
    <div>
      <button onClick={handleConnect}>Connect Audible</button>
      <input onBlur={(e) => handleUrlPaste(e.target.value)} />
    </div>
  );
}

Browser Configuration

The browser bundle uses Node.js crypto module for random generation and hashing. Your bundler must provide a polyfill.

Vite

// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  resolve: {
    alias: {
      crypto: 'crypto-browserify',
      stream: 'stream-browserify',
      buffer: 'buffer',
    },
  },
  define: {
    'process.env': {},
    global: 'globalThis',
  },
  optimizeDeps: {
    esbuildOptions: {
      define: {
        global: 'globalThis',
      },
    },
  },
});

Then install polyfills:

npm install crypto-browserify stream-browserify buffer

Webpack 5

// webpack.config.js
module.exports = {
  resolve: {
    fallback: {
      crypto: require.resolve('crypto-browserify'),
      stream: require.resolve('stream-browserify'),
      buffer: require.resolve('buffer/'),
    },
  },
};

Note on Browser Limitations

Only these functions work in browsers:

  • generateAuthUrl() - Creates OAuth URLs
  • buildInitCookies() - Generates CAPTCHA-reducing cookies
  • parseCallbackUrl() - Extracts auth codes from URLs
  • validateCallbackUrl() - Validates callback URLs

All API calls (registerDevice, getLibrary, getDownloadUrl, etc.) require a server proxy due to CORS restrictions.

API Reference

Authentication

generateAuthUrl(locale: string): AuthUrlResult

Generates Amazon OAuth URL for device registration.

const result = generateAuthUrl('us');
// result.url - OAuth URL to open
// result.codeVerifier - Save for registerDevice
// result.serial - Save for registerDevice
// result.expectedRedirectDomain - "audible.com" etc.
// result.instructions - User-facing instructions

Supported locales: us, uk, ca, au, de, fr, in, it, jp

buildInitCookies(): InitCookies

Generates cookies that reduce CAPTCHA frequency by ~80%.

const cookies = buildInitCookies();
// cookies.frc - Random fingerprint
// cookies['map-md'] - Device metadata
// cookies['amzn-app-id'] - App identifier

Set these cookies before opening the OAuth URL (requires browser extension or manual cookie setting).

parseCallbackUrl(url: string): CallbackResult

Extracts authorization code from callback URL.

const { authorizationCode } = parseCallbackUrl(callbackUrl);

Throws error if authorization code not found.

validateCallbackUrl(url: string): ValidationResult

Validates callback URL and extracts code with error handling.

const result = validateCallbackUrl(url);
if (result.valid) {
  console.log(result.authorizationCode);
} else {
  console.error(result.error);
}

Use this for real-time validation as users paste URLs.

registerDevice(params: RegisterDeviceParams): Promise<RegisterDeviceResult>

Registers device with Amazon and returns credentials.

const credentials = await registerDevice({
  authorizationCode,
  codeVerifier,
  serial,
  localeCode: 'us',
});

Returns access token, refresh token, device private key, ADP token, and activation bytes.

refreshAccessToken(params: RefreshTokenParams): Promise<RefreshTokenResult>

Refreshes expired access token.

const { accessToken, expiresIn } = await refreshAccessToken({
  refreshToken,
  localeCode: 'us',
});

Access tokens expire after 60 minutes.

Library Management

getLibrary(client: AudibleClient): Promise<LibraryItem[]>

Fetches user's audiobook library.

const authenticator = new Authenticator(credentials);
const client = new AudibleClient(authenticator, 'us');
const library = await getLibrary(client);

library.forEach(book => {
  console.log(book.title);
  console.log(book.authors);
  console.log(book.asin);
});

getDownloadUrl(client: AudibleClient, asin: string): Promise<DownloadInfo>

Gets download URL for audiobook.

const { downloadUrl } = await getDownloadUrl(client, 'B002V1A0WE');
// Download the AAX file from downloadUrl

Download URLs expire after a short period.

Auth File Compatibility

Read existing Python audible-cli auth files:

import { parseAuthFile } from 'audible-core';

const authFile = JSON.parse(fs.readFileSync('auth.json', 'utf-8'));
const credentials = await parseAuthFile(authFile);

const authenticator = new Authenticator(credentials);
// Use authenticator...

Architecture

Node.js Build

The main export (audible-core) includes all functionality:

  • Authentication (OAuth, device registration, token refresh)
  • API client (with RSA signing)
  • Library operations
  • Download URL generation

Browser Build

The browser export (audible-core/browser) includes only client-side utilities:

  • OAuth URL generation
  • Cookie generation
  • URL validation and parsing

API operations require a server proxy due to:

  1. CORS - Audible API doesn't set CORS headers
  2. RSA Signing - API requests need device private key signatures
  3. Security - Private keys shouldn't be exposed in browser

Example: React App with Express Proxy

React Frontend

// src/auth/AudibleAuth.tsx
import { generateAuthUrl, validateCallbackUrl } from 'audible-core/browser';

export function AudibleAuth() {
  const [authUrl, setAuthUrl] = useState('');

  const startAuth = async () => {
    const { url, codeVerifier, serial } = generateAuthUrl('us');
    // Store codeVerifier and serial in localStorage
    localStorage.setItem('audible_verifier', codeVerifier);
    localStorage.setItem('audible_serial', serial);
    setAuthUrl(url);
  };

  const completeAuth = async (callbackUrl: string) => {
    const result = validateCallbackUrl(callbackUrl);
    if (!result.valid) {
      alert(result.error);
      return;
    }

    // Send to server
    const response = await fetch('/api/audible/register', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        authorizationCode: result.authorizationCode,
        codeVerifier: localStorage.getItem('audible_verifier'),
        serial: localStorage.getItem('audible_serial'),
      }),
    });

    const credentials = await response.json();
    // Store credentials securely
  };

  return <div>...</div>;
}

Express Backend

// server.ts
import express from 'express';
import { registerDevice, Authenticator, AudibleClient, getLibrary } from 'audible-core';

const app = express();

app.post('/api/audible/register', async (req, res) => {
  const { authorizationCode, codeVerifier, serial } = req.body;

  const credentials = await registerDevice({
    authorizationCode,
    codeVerifier,
    serial,
    localeCode: 'us',
  });

  // Store credentials in your database
  // Return to client (or just confirmation)
  res.json({ success: true });
});

app.get('/api/audible/library', async (req, res) => {
  // Get credentials from session/database
  const credentials = getUserCredentials(req.user.id);

  const authenticator = new Authenticator(credentials);
  const client = new AudibleClient(authenticator, 'us');
  const library = await getLibrary(client);

  res.json(library);
});

Testing

npm test

Runs 34 tests covering:

  • OAuth URL generation
  • Cookie generation
  • URL validation
  • Device registration
  • Token refresh
  • Library operations
  • Error handling

Why the Manual URL Copy?

Amazon restricts OAuth redirect URLs to Amazon/Audible domains only. This prevents custom callbacks to your application. All Audible tools (OpenAudible, Audiobookshelf, audible-cli) use the same manual URL paste flow.

The buildInitCookies() function significantly reduces CAPTCHA frequency, which improves the experience despite manual URL entry.

Activation Bytes

Activation bytes decrypt AAX files to M4B format. The package retrieves activation bytes during device registration. Use ffmpeg or audible-cli for decryption:

ffmpeg -activation_bytes 1CEB00DA -i audiobook.aax -c copy audiobook.m4b

Security Notes

  1. Never commit credentials - Store in environment variables or secure vaults
  2. Rotate tokens - Access tokens expire after 60 minutes; refresh proactively
  3. Protect private keys - Device private keys authenticate API requests
  4. HTTPS only - Never transmit credentials over HTTP
  5. Browser security - Don't store credentials in localStorage; use httpOnly cookies

Contributing

This package extracts functionality from the Python audible and audible-cli libraries. Credit to @mkb79 for the original implementation research.

License

ISC