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

podcast-index-api

v2.0.0

Published

Lightweight, zero-dependency Node.js client for the Podcast Index API.

Readme

Podcast Index API

Lightweight, zero-dependency Node.js client for the Podcast Index API.

npm node CI Downloads Install size pipeline status

Source | npm | API docs

A thin, promise-based wrapper around every Podcast Index API endpoint. It has no runtime dependencies — it uses the built-in fetch and crypto from Node.js.

Requirements

  • Node.js >= 22 — the library uses the global fetch.
  • API credentials — a free key/secret from https://api.podcastindex.org/.
  • A User-Agent that identifies your app. The API rejects requests that omit it or use a generic/sample value, so you must supply your own.

Installation

npm install podcast-index-api

Quick start

const podcastIndexApi = require('podcast-index-api')

const api = podcastIndexApi(
    process.env.PODCAST_INDEX_KEY,
    process.env.PODCAST_INDEX_SECRET,
    'my-app/1.0 (https://example.com)', // your own User-Agent
)

async function main() {
    const { feeds } = await api.searchByTerm('The Joe Rogan Experience')
    console.log(feeds[0].title)
}

main().catch(console.error)

All three constructor arguments are required; the factory throws if any is missing.

ESM / import

The package is CommonJS, but it works from ES modules (and TypeScript) via a default import:

import podcastIndexApi from 'podcast-index-api'

const api = podcastIndexApi(key, secret, userAgent)

// the error class is available on the default import:
const { PodcastIndexError } = podcastIndexApi

Usage

Every method returns a Promise that resolves to the parsed JSON response.

// async / await
const results = await api.searchByTerm('Joe Rogan Experience')

// or with .then()
api.searchByTerm('Joe Rogan Experience').then((results) => {
    console.log(results)
})

Return values

Methods resolve to the raw JSON returned by the Podcast Index API — the library does not reshape it. See the official API docs for the fields each endpoint returns. For example, searchByTerm resolves to something like:

{
    "status": "true",
    "feeds": [{ "id": 550168, "title": "The Joe Rogan Experience" /* ... */ }],
    "count": 8,
    "query": "The Joe Rogan Experience",
}

Error handling

When a request fails — an HTTP 500, a non-2xx auth/WAF response, or a body with status: "false" — the method rejects with a PodcastIndexError, a real Error subclass:

const podcastIndexApi = require('podcast-index-api')
const { PodcastIndexError } = podcastIndexApi

try {
    await api.podcastsByFeedUrl('http://example.com/not-a-feed')
} catch (err) {
    if (err instanceof PodcastIndexError) {
        console.error(err.message) // e.g. "Feed url not found."
        console.error(err.code) // HTTP status code, e.g. 400
        console.error(err.body) // parsed JSON error payload, when available
    }
}

The low-level api(path) method does not throw on API errors — it resolves with { statusCode, body }. Use the named methods (or custom) for normal use.

TypeScript

Type declarations ship with the package (index.d.ts) — no @types package needed. You get autocomplete for every method and its parameters out of the box.

import podcastIndexApi from 'podcast-index-api' // needs esModuleInterop
// or: import podcastIndexApi = require('podcast-index-api')

const api = podcastIndexApi(key, secret, userAgent)

Functions

  • Custom
    • Use for endpoints that don't have a specific function or if the function doesn't accept an argument for a desired parameter.
      • custom(path: String, queries: Object)
  • Search
    • searchByTerm(q: String, val: String, clean: Boolean, fullText: Boolean)
    • searchByTitle(q: String, val: String, clean: Boolean, fullText: Boolean)
    • searchEpisodesByPerson(q: String, fullText: Boolean)
  • Podcasts
    • podcastsByFeedUrl(feedUrl: String)
    • podcastsByFeedId(feedId: Number)
    • podcastsByFeedItunesId(itunesId: Number)
    • podcastsByGUID(guid: String)
    • podcastsByTag()
    • podcastsTrending(max: Number, since: Number, lang: String, cat: String, notcat: String)
    • podcastsDead()
  • Episodes
    • episodesByFeedId(feedId: Number, since: Number, max: Number, fullText: Boolean)
    • episodesByFeedUrl(feedUrl: String, since: Number, max: Number, fullText: Boolean)
    • episodesByItunesId(itunesId: Number, since: Number, max: Number, fullText: Boolean)
    • episodesById(id: Number, fullText: Boolean)
    • episodesRandom(max: Number, lang: String, cat: String, notcat: String, fullText: Boolean)
  • Recent
    • recentFeeds(max: Number, since: Number, cat: String, lang: String, notcat: String)
    • recentEpisodes(max: Number, excludeString: String, before: Number, fullText: Boolean)
    • recentNewFeeds(max: Number, since: Number)
    • recentSoundbites(max: Number)
  • Value
    • valueByFeedUrl(feedUrl: String)
    • valueByFeedId(feedId: Number)
  • Categories
    • categoriesList()
  • Notify Hub
    • hubPubNotifyById(feedId: Number)
    • hubPubNotifyByUrl(feedUrl: String)
  • Add
    • addByFeedUrl(feedUrl: String, chash: String, itunesId: Number)
    • addByItunesId(itunesId: Number)

Migrating to v2

v2.0.0 modernized the library. Breaking changes:

  • Node.js >= 22 is required. The library now uses the built-in fetch; the got dependency was removed, so there are zero runtime dependencies.
  • A User-Agent is now required. It used to be optional with a built-in default, but the API now blocks that default — pass your own as the third argument.
  • Errors are now PodcastIndexError instances (still carrying .code and .message, now also .body). Existing code that catches errors and reads err.code / err.message keeps working.

See the CHANGELOG for full details.

License

MIT