{
  "openapi": "3.0.1",
  "info": {
    "title": "Apple Podcasts Scraper – Episodes, Reviews & Podcast Publishers",
    "description": "Scrape Apple Podcasts: every episode (title, date, duration, description, audio URL, RSS feed), listener reviews with star ratings, keyword search, the top-shows or trending-episodes chart per storefront, or every show a publisher runs. HTTP-only, no login, pay per result. iTunes podcast data API.",
    "version": "0.1",
    "x-build-id": "xfzOQQ8uESaNcMWg4"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/fetchsmith~apple-podcasts-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-fetchsmith-apple-podcasts-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/fetchsmith~apple-podcasts-scraper/runs": {
      "post": {
        "operationId": "runs-sync-fetchsmith-apple-podcasts-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/fetchsmith~apple-podcasts-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-fetchsmith-apple-podcasts-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "dataType": {
            "title": "What to scrape",
            "enum": [
              "episodes",
              "reviews",
              "podcasts",
              "charts",
              "publisher"
            ],
            "type": "string",
            "description": "episodes = every episode of the given shows; reviews = listener reviews and star ratings; podcasts = the show records themselves (use with Search terms to discover shows); charts = today's top podcasts in a storefront (no podcasts/search terms needed); publisher = every show published by a given publisher/artist.",
            "default": "episodes"
          },
          "podcasts": {
            "title": "Podcasts / publishers",
            "type": "array",
            "description": "Apple Podcasts show URLs/IDs, e.g. https://podcasts.apple.com/us/podcast/lex-fridman-podcast/id1434243584 or 1434243584. Leading/trailing spaces are ignored. For dataType 'publisher', give the publisher's Apple Podcasts artist URL/ID instead, e.g. https://podcasts.apple.com/us/artist/the-new-york-times/121664449. You can also paste a direct RSS/podcast feed URL for any show, including ones not on Apple Podcasts — works with dataType 'episodes' only, since the feed has no Apple ID for reviews/search/charts.",
            "items": {
              "type": "string"
            }
          },
          "searchTerms": {
            "title": "Search terms",
            "type": "array",
            "description": "Find shows by keyword instead of (or as well as) giving URLs. Each match is then scraped according to 'What to scrape'.",
            "items": {
              "type": "string"
            }
          },
          "chartType": {
            "title": "Chart",
            "enum": [
              "shows",
              "episodes"
            ],
            "type": "string",
            "description": "Charts only: which Apple chart to pull. \"Top Shows\" ranks podcasts; \"Trending Episodes\" is Apple's separate chart of individual episodes (one row per episode, with audio URL, duration and release date). Trending Episodes has no genre breakdown, so \"Chart genre\" is ignored for it.",
            "default": "shows"
          },
          "chartCount": {
            "title": "Chart size",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Charts only: how many chart entries to fetch for the storefront. Apple caps the overall charts (Top Shows and Trending Episodes) at 100; a genre chart goes up to 200. Anything higher is clamped, with a warning.",
            "default": 50
          },
          "chartGenre": {
            "title": "Chart genre",
            "enum": [
              "",
              "arts",
              "business",
              "comedy",
              "education",
              "fiction",
              "government",
              "healthFitness",
              "history",
              "kidsFamily",
              "leisure",
              "music",
              "news",
              "religionSpirituality",
              "science",
              "societyCulture",
              "sports",
              "technology",
              "trueCrime",
              "tvFilm"
            ],
            "type": "string",
            "description": "Charts only: restrict the Top Shows chart to one Apple Podcasts category instead of the overall top chart. Leave empty for the overall chart. Ignored when \"Chart\" is Trending Episodes (Apple publishes no per-genre episode chart).",
            "default": ""
          },
          "searchLimit": {
            "title": "Podcasts per search term",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "How many shows to take from each search term (max 200).",
            "default": 10
          },
          "country": {
            "title": "Country storefront",
            "type": "string",
            "description": "Two-letter ISO-3166-1 alpha-2 storefront code (us, gb, de, ...) — the UK is \"gb\", not \"uk\". Availability, charts and reviews differ per storefront.",
            "default": "us"
          },
          "maxEpisodesPerPodcast": {
            "title": "Max episodes per podcast",
            "minimum": 1,
            "maximum": 20000,
            "type": "integer",
            "description": "Apple's episode endpoint exposes up to 200 of the most recent episodes per show. With 'Use RSS for full archive' enabled, this can go up to 20,000 since RSS has no such cap. What it counts differs by source, because only one of them can be re-read: on Apple's API it is the number of recent episodes FETCHED (the API's own limit), so a date/duration/explicit filter narrows within them and cannot reach older ones; on RSS the whole feed arrives in one request, so it caps the episodes KEPT after filtering and a date window is free to match anywhere in the archive.",
            "default": 100
          },
          "maxPodcastsPerPublisher": {
            "title": "Max podcasts per publisher",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "dataType 'publisher' only: how many shows to return per publisher (Apple's lookup endpoint returns up to 200).",
            "default": 200
          },
          "maxReviewsPerPodcast": {
            "title": "Max reviews per podcast",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Apple exposes up to 500 reviews (10 pages of 50) per show per storefront. This cap counts reviews scanned before minRating/maxRating/keyword filtering, not results kept — see README FAQ.",
            "default": 200
          },
          "sort": {
            "title": "Review sort",
            "enum": [
              "mostRecent",
              "mostHelpful"
            ],
            "type": "string",
            "description": "Only applies to reviews.",
            "default": "mostRecent"
          },
          "includePodcastInfo": {
            "title": "Include show metadata on every row",
            "type": "boolean",
            "description": "Attach show name, host, genre, RSS feed URL and episode count to each episode/review row.",
            "default": true
          },
          "maxResults": {
            "title": "Max results (total)",
            "minimum": 1,
            "maximum": 50000,
            "type": "integer",
            "description": "Overall cap across all shows — also caps what you pay for.",
            "default": 2000
          },
          "minRating": {
            "title": "Minimum star rating",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Reviews only: keep reviews rated >= this (1-5)."
          },
          "maxRating": {
            "title": "Maximum star rating",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Reviews only: keep reviews rated <= this (1-5)."
          },
          "keyword": {
            "title": "Keyword filter",
            "type": "string",
            "description": "Reviews only: keep reviews whose title or text contains this word/phrase (case-insensitive). Leading/trailing spaces are ignored. Accented letters are Unicode-normalized before matching, so \"café\" matches regardless of which Unicode form (composed or decomposed) you typed it in."
          },
          "minReleaseDate": {
            "title": "Episodes released on/after",
            "type": "string",
            "description": "Episodes only: keep episodes released on or after this date (YYYY-MM-DD or full ISO). Note: Apple's episode lookup only returns the most recent 'Max episodes per podcast' episodes, so this narrows within that recent window and cannot reach further back into a show's archive than Apple already returned — enable 'Use RSS for full archive' to search further back."
          },
          "maxReleaseDate": {
            "title": "Episodes released on/before",
            "type": "string",
            "description": "Episodes only: keep episodes released on or before this date (YYYY-MM-DD or full ISO). Same recent-window caveat as 'Episodes released on/after'."
          },
          "useRssForFullArchive": {
            "title": "Use RSS for full archive (beyond Apple's ~200-episode cap)",
            "type": "boolean",
            "description": "Episodes only: fetch each show's own RSS feed instead of Apple's lookup API, which returns only the most recent ~200 episodes. RSS feeds have no such cap (a real feed tested returned 2,977 episodes) and also carry fields Apple's API never exposes: episode type (full/trailer/bonus), full HTML show notes, audio file size and a transcript URL when the publisher provides one (Podcasting 2.0). Costs one extra request per show; Apple's lookup API is used as a fallback for any show without a usable feed. Default off to keep existing run behavior unchanged.",
            "default": false
          },
          "minDurationSeconds": {
            "title": "Minimum episode duration (seconds)",
            "minimum": 0,
            "type": "integer",
            "description": "Episodes only: drop episodes shorter than this — useful for excluding trailers, ads or short teasers. Apple omits the duration for a large share of episodes on some shows regardless of their real length; those episodes are always kept, never assumed short (the run log reports how many). Leave empty to keep all lengths."
          },
          "explicitFilter": {
            "title": "Explicit content filter",
            "enum": [
              "all",
              "clean",
              "explicitOnly"
            ],
            "type": "string",
            "description": "Episodes only: 'all' keeps everything (default), 'clean' excludes episodes flagged Explicit, 'explicitOnly' keeps only episodes flagged Explicit. The flag comes from whichever source the run uses: Apple's Store rating by default, or the show's own <itunes:explicit> tag when 'Use RSS for full archive' is on (falling back to the show-level tag for episodes that carry none). The two can disagree for the same episode, so a filter that returns nothing under one source may return rows under the other.",
            "default": "all"
          },
          "webhookUrl": {
            "title": "Webhook URL (notify on completion)",
            "type": "string",
            "description": "Optional. An http(s) URL to POST a small JSON summary to when the run finishes — items pushed, dataType, and the run's dataset ID so you can fetch the results. A convenience for callers who want a completion ping without setting up an Apify platform webhook (which needs separate Console/API configuration per Task, not per run). Best-effort: a failed or slow webhook is logged as a warning and never fails the run or affects charging — it fires after every item has already been pushed and charged. Leave empty to skip."
          },
          "watchLabel": {
            "title": "Watch label (only new episodes since last run)",
            "type": "string",
            "description": "Optional, dataType \"episodes\" only. Name a saved watch (e.g. \"my-daily-check\") and this run returns ONLY episodes not delivered under that same label and filter set before, instead of every episode every time. The first run for a label is a free baseline: it records which episodes already exist and returns zero rows. Run it again later — on a schedule, typically — to get only what's new. The baseline is kept in your own Apify account (a named key-value store), keyed by label plus a fingerprint of your other filters, so changing a filter starts a fresh baseline instead of dumping previously-excluded episodes as \"new\". Ignored for dataType other than \"episodes\"."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}