audible-core
v1.0.0
Published
TypeScript library for Audible API authentication and library management
Maintainers
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-coreFor local development:
# In audible-core directory
npm link
# In your project
npm link audible-coreQuick 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 bufferWebpack 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 URLsbuildInitCookies()- Generates CAPTCHA-reducing cookiesparseCallbackUrl()- Extracts auth codes from URLsvalidateCallbackUrl()- 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 instructionsSupported 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 identifierSet 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 downloadUrlDownload 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:
- CORS - Audible API doesn't set CORS headers
- RSA Signing - API requests need device private key signatures
- 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 testRuns 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.m4bSecurity Notes
- Never commit credentials - Store in environment variables or secure vaults
- Rotate tokens - Access tokens expire after 60 minutes; refresh proactively
- Protect private keys - Device private keys authenticate API requests
- HTTPS only - Never transmit credentials over HTTP
- 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
