The podsearch package for finding podcasts

Apple doesn’t really advertise that the iTunes Store and other directories have a crooked but simple search API - so I decided to write about it. This post will show you what the API can do and how to use it.

Apple Directory Search


API searches the contents of the iTunes Store, iBooks Store, Apple Podcasts, and App Store. Accordingly, you can find songs, movies, books, podcasts and applications.

API works according to the long-forgotten principle JSONP , that is, returns CDMY0CDMY instead of normal CDMY1CDMY.

GET/search?media=podcast&term=python HTTP/1.1 Host: Accept: application/json HTTP/2 200 content-type: text/javascript; charset=utf-8 {...} 

Of course, this feature can simply be ignored:

import requests def search(term, media): url="" payload={"term": term, "media": media} response=requests.get(url, params=payload) response.raise_for_status() results=response.json().get("results", []) return results 

>>> results=search("python", media="podcast") >>> results[0]["collectionName"] 'Talk Python To Me' 

Request parameters

Search can be customized:

  • CDMY2CDMY - search query, the only required parameter;
  • CDMY12CDMY - country of production, two-character ISO code (CDMY13CDMY, CDMY14CDMY,.), By default CDMY15CDMY;
  • CDMY16CDMY - the maximum number of results, by default CDMY17CDMY.

Example of a function that supports all parameters:

import requests def search(term, media="all", country="us", limit=10): url="" payload={"term": term, "media": media, "country": country, "limit": limit} response=requests.get(url, params=payload) response.raise_for_status() results=response.json().get("results", []) return results 


General response structure:

{ "resultCount": 10, "results": [ { "wrapperType": "track", "kind": "song", "artistId": 1495668306, "collectionId": 527039271, "trackId": 527039276, "artistName": "Dodge & Fuski", "collectionName": "Never Say Die (Deluxe Edition)", "trackName":"Python", ... }, { "wrapperType": "track", "kind": "podcast", "collectionId": 979020229, "trackId": 979020229, "artistName": "Michael Kennedy (@mkennedy)", "collectionName": "Talk Python To Me" ... }, ... ] } 

The specific set of fields depends on the type of work (CDMY18CDMY) and is not fully described anywhere, as far as I know. Often filled:

  • CDMY19CDMY - identifier of the author of the work;
  • CDMY20CDMY - author;
  • CDMY21CDMY - link to the author on Apple;
  • CDMY22CDMY - album identifier;
  • CDMY23CDMY - album name;
  • CDMY24CDMY - link to the album on Apple;
  • CDMY25CDMY - composition identifier;
  • CDMY26CDMY - the name of the composition;
  • CDMY27CDMY - link to a preview of the work 100x100 pixels;
  • CDMY28CDMY - country of work;
  • CDMY29CDMY - the genre of the work.

For podcasts, I made a typed wrapper - package podsearch , you can see the set of fields in it.

Request by ID

If the object identifier is known (CDMY30CDMY, CDMY31CDMY, CDMY32CDMY), you can call the CDMY33CDMY method on it:

import requests def lookup(object_id): url="" payload={"id": object_id} response=requests.get(url, params=payload) response.raise_for_status() results=response.json().get("results", []) return results 

>>> results=lookup(979020229) >>> results[0]["collectionName"] 'Talk Python To Me' 


I already mentioned the unusual Content-Type of the answer. In addition:

  • The country of the work (CDMY34CDMY) is both in the request parameters and in the response. But in the parameters it’s a two-character ISO code (CDMY35CDMY), and in the answer it’s a three-character ISO code (CDMY36CDMY).
  • There is no response scheme.
  • Apple limits the frequency of API calls to 20 requests per minute.

Apple API Description
Podcast Search Packet

If you want more interesting things in Python, subscribe to the @ohmypy