Skip to content

About

Product repo: client for the AppBlockList App Lookup API: filtering categories, age rating and iOS/Android IDs for 1.87M apps

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AppBlockList

App categorization and MDM app blocklists for iOS and Android. This repository is the home of the open-source AppBlockList clients: it documents the App Lookup API, the six blocklist feed formats and the official libraries for ten languages.

AppBlockList answers one question for device administrators and developers: what kind of app is this? Send an iOS bundle ID, an App Store ID or an Android package name and get back the app's ranked filtering categories, age rating, genre, developer and both store identifiers.


At a glance

Filtering categories 58, ranked per app, shared with 120 million categorized web domains
Apps in the Mobile App Database 1,874,397 iPhone and iPad apps
Apps with a known Android twin about 800,000
Google Play package names tracked 3.9 million
App Store genres 26
Feed refresh every month
Feed formats 6
Client libraries Node.js, Python, Go, Rust, Java, .NET, PHP, Ruby, Dart, Elixir
License of the clients MIT

Three ways to use the data

Product Who it is for What you get
App Lookup API developers, MDM integrators one JSON record per app, on demand
MDM App Blocklist Feed school and business IT teams ready-to-import block lists in six formats, refreshed monthly
Mobile App Database analysts, security vendors a licensed file with 12 columns per app

The rest of this README covers the API first, then the feed formats, then the client libraries and worked examples.

The App Lookup API

Request

GET https://www.appblocklist.com/api/v1/app?id=<ID>&api_key=<KEY>

The key may be sent as a header instead, which keeps it out of server logs:

GET https://www.appblocklist.com/api/v1/app?id=<ID>
X-API-Key: <KEY>

id accepts:

  • an iOS bundle ID, for example com.zhiliaoapp.musically
  • an App Store ID, as digits (835599320) or with the id prefix (id835599320)
  • an Android package name, for example com.openai.chatgpt

The maximum length is 200 characters.

Response

{
  "found": true,
  "name": "TikTok - Videos, Shop & LIVE",
  "developer": "TikTok Ltd.",
  "bundle_id": "com.zhiliaoapp.musically",
  "app_store_id": "835599320",
  "android_package": "com.zhiliaoapp.musically",
  "app_store_genre": "Entertainment",
  "age_rating": "12+",
  "filtering_categories": ["Social Networking", "Streaming Media"],
  "developer_domain": "tiktok.com",
  "iab_category": "Technology & Computing > Computing > Internet > Social Networking"
}
Field Type Description
found boolean true when the app is categorized
name string App Store name
developer string publisher
bundle_id string iOS bundle identifier
app_store_id string numeric App Store ID, returned as a string
android_package string Google Play twin when the app is on both stores, otherwise ""
app_store_genre string App Store genre
age_rating string 4+, 9+, 12+ or 17+
filtering_categories string[] one or more of 58 categories, most descriptive first
developer_domain string publisher's web domain
iab_category string IAB content taxonomy path

The body is plain JSON as defined by RFC 8259, so any language can read it without a client library.

Status codes

Code Body What to do
200 the record above use it; one lookup is counted
400 {"error": ...} the id is missing or is not a bundle ID, App Store ID or package name
401 {"error": ...} send a valid api_key or X-API-Key
403 {"error": ..., "monthly_lookups": ...} the key has used its monthly lookups
404 {"found": false, "error": "App not found."} unknown app, treat as data
404 {"found": false, "android_package": "...", "error": "Listed on Google Play, not yet in the categorized database."} real Play app, queue for review
500 {"error": ...} temporary, retry with backoff

Usage rules

  1. One ID per request.
  2. Send requests one after another; avoid parallel bursts.
  3. Only a 200 answer counts as a lookup.

All official clients follow these rules: they never fan out requests and they treat a 404 as a normal result with found = false rather than an exception.

The 58 filtering categories

Each app gets one or more categories, ranked. A few examples of the names you will see in filtering_categories:

Group Example categories
Social and communication Social Networking, Email and Messaging, Dating, Forums / Message Boards, Community Sites
Entertainment Gaming, Streaming Media, Arts & Entertainment, Podcasts
Risk Gambling, Adult, VPN / Proxy / Anonymizers, Remote Access Tools, Illegal Drugs, Weapons, Violence
Work and study Education/Reference, Business, Web-based Applications, Developer Tools / Code Hosting, Webinars/E-learning
Money Financial Services, Online Banking, Cryptocurrency, Shopping
Emerging AI / LLM Tools

These are the same category names applied to 120 million domains in the web filtering database. If your DNS filter blocks Gambling, the matching app rule uses the identical string.

The six MDM feed formats

Subscribers to App Blocklists for MDM receive a monthly feed covering all 58 categories. Every category is delivered in each of these formats:

# Format File type Where it goes
1 iOS bundle ID list plain text, one ID per line any MDM that accepts a pasted list of bundle IDs
2 Android package list plain text, one package per line Android Enterprise managed Play policies, Google Admin
3 Configuration profile .mobileconfig, Restrictions payload com.apple.applicationaccess with blockedAppBundleIDs Apple Configurator, any Apple MDM
4 Intune import Intune import files Microsoft Intune app restriction policies
5 Jamf import Jamf import files Jamf Pro and Jamf School restrictions
6 Full CSV name, developer, both IDs, genre, age rating, categories spreadsheets, SIEM, custom tooling

Districts and IT providers get separate files per school or client. Guides for each console: Intune, Jamf, Google Admin and mobileconfig profiles.

Client libraries

Every client is MIT licensed, sends appblocklist-<lang>/1.0.0 (+https://www.appblocklist.com) as its User-Agent, reads the key from APPBLOCKLIST_API_KEY when none is passed, exposes lookup(id) and raises typed errors for 400, 401, 403 and 500.

Language Install Repository
Node.js npm install appblocklist npm package
Python pip install appblocklist PyPI project
Go go get github.com/explainableaixai/appblocklist-go appblocklist-go
Rust cargo add appblocklist appblocklist-rust
Java Maven com.alphaquantum:appblocklist:1.0.0 appblocklist-java
.NET dotnet add package AppBlockList appblocklist-dotnet
PHP composer require alphaquantum/appblocklist appblocklist-php
Ruby gem install appblocklist appblocklist-ruby
Dart dart pub add appblocklist appblocklist-dart
Elixir {:appblocklist, "~> 1.0"} in mix.exs appblocklist-elixir

Each repository has its own README with the exact install line, a method table and tests that run without network access.

Worked examples

curl: one lookup

curl -s -H "X-API-Key: $APPBLOCKLIST_API_KEY" \
  "https://www.appblocklist.com/api/v1/app?id=id835599320"

Show only what matters for a policy decision with jq:

curl -s -H "X-API-Key: $APPBLOCKLIST_API_KEY" \
  "https://www.appblocklist.com/api/v1/app?id=com.openai.chatgpt" \
  | jq '{found, name, age_rating, filtering_categories}'

Print the HTTP status alongside the body, useful when debugging keys:

curl -s -o /tmp/app.json -w '%{http_code}\n' \
  -H "X-API-Key: $APPBLOCKLIST_API_KEY" \
  "https://www.appblocklist.com/api/v1/app?id=com.example.unknown"
cat /tmp/app.json

Shell: categorize an inventory into a CSV

This script reads one ID per line, respects the one-at-a-time rule, retries on 500 and stops on 401 or 403.

#!/usr/bin/env bash
# categorize.sh  inventory.txt > categorized.csv
set -euo pipefail
: "${APPBLOCKLIST_API_KEY:?set APPBLOCKLIST_API_KEY}"
API="https://www.appblocklist.com/api/v1/app"

echo "id,found,name,bundle_id,android_package,age_rating,categories"
sort -u "$1" | while read -r id; do
  [ -z "$id" ] && continue
  for attempt in 1 2 3; do
    code=$(curl -s -o /tmp/abl.json -w '%{http_code}' -G "$API" \
      --data-urlencode "id=$id" -H "X-API-Key: $APPBLOCKLIST_API_KEY")
    [ "$code" != "500" ] && break
    sleep $((attempt * 2))
  done
  case "$code" in
    200|404)
      jq -r --arg id "$id" '[$id, .found, .name // "", .bundle_id // "", .android_package // "",
            .age_rating // "", ((.filtering_categories // []) | join("; "))] | @csv' /tmp/abl.json ;;
    401|403)
      echo "stopping: HTTP $code $(jq -r .error /tmp/abl.json)" >&2; exit 1 ;;
    *)
      echo "\"$id\",error,,,,,HTTP $code" ;;
  esac
  sleep 0.2
done

Shell: filter that CSV into block lists

# Every app in a blocked category, split by platform
BLOCK='Gambling|Adult|Dating|VPN / Proxy / Anonymizers'
grep -E "$BLOCK" categorized.csv | csvcut -c bundle_id      | tail -n +2 | grep -v '^$' > blocked-ios.txt
grep -E "$BLOCK" categorized.csv | csvcut -c android_package | tail -n +2 | grep -v '^$' > blocked-android.txt
wc -l blocked-*.txt

(csvcut comes from csvkit; any CSV tool works.)

Python: plain requests, no client library

import os
import time
import requests

API = "https://www.appblocklist.com/api/v1/app"
HEADERS = {"X-API-Key": os.environ["APPBLOCKLIST_API_KEY"]}

def lookup(app_id):
    for attempt in range(3):
        r = requests.get(API, params={"id": app_id}, headers=HEADERS, timeout=15)
        if r.status_code != 500:
            break
        time.sleep(2 * (attempt + 1))
    if r.status_code in (200, 404):
        return r.json()
    raise RuntimeError("HTTP {}: {}".format(r.status_code, r.json().get("error")))

for app_id in ["com.zhiliaoapp.musically", "com.openai.chatgpt", "835599320"]:
    rec = lookup(app_id)
    print(app_id, rec.get("found"), rec.get("filtering_categories"))
    time.sleep(0.2)

Python: the same job with the appblocklist package

from appblocklist import AppBlockList, AppResult

client = AppBlockList()  # APPBLOCKLIST_API_KEY
STUDENT_POLICY = {"Gambling", "Adult", "Dating", "Social Networking", "VPN / Proxy / Anonymizers"}

inventory = open("inventory.txt").read().split()
results = client.lookup_many(inventory, pause=0.2)

for r in results:
    if isinstance(r, AppResult) and r.found:
        verdict = "BLOCK" if set(r.filtering_categories) & STUDENT_POLICY or r.age_rating == "17+" else "allow"
        print("{:<6} {:<40} {}".format(verdict, r.name[:40], r.primary_category))

Python: Android twins from an iOS-only inventory

android_blocklist = sorted({
    r.android_package
    for r in results
    if isinstance(r, AppResult) and r.found and r.android_package
    and set(r.filtering_categories) & STUDENT_POLICY
})
open("blocked-android.txt", "w").write("\n".join(android_blocklist) + "\n")

Because each record carries both identifiers, a single iPad inventory yields the matching Android policy for every app that exists on both stores.

Why AppBlockList

  • Apps and websites in one taxonomy. The 58 categories are shared with the domain side, so a "block Gambling" policy means the same thing on the network and on the device.
  • Both platforms per record. iOS and Android identifiers arrive together for about 800,000 apps.
  • Policy-ready fields. Ranked categories, age rating and genre cover the questions school and business policies usually ask.
  • Files or API, your choice. Use the monthly feed when you want lists, the API when you want decisions in your own code, and the database when you want everything offline.
  • Predictable pricing. Plans are per organization, never per device.

Plans

Product Price
App Lookup API $99 per month for 100,000 lookups; higher volumes quoted
App Blocklists for MDM, School or Business $99/month or $990/year per organization
App Blocklists for MDM, Districts and IT Providers $249/month or $2,490/year, unlimited schools or client organizations, includes the API with 100,000 lookups a month
Mobile App Database, top 100,000 apps $999 one-time
Mobile App Database, top 500,000 apps $1,999 one-time

Details: appblocklist.com/pricing.php.

FAQ

Is there a free way to try a lookup?

The bundle ID lookup tool and the package name lookup tool on the website show categories for individual apps in the browser.

Why do some apps return an Android package and others an empty string?

android_package is filled only when the same app is published on Google Play. Apple-only apps return "".

How should a client handle a 404?

As data. "This app is not categorized" is a normal answer in an inventory loop, so every official client returns a result with found = false instead of throwing.

Which category should a rule use, the first or any?

Both work. The list is ranked, so filtering_categories[0] is the most descriptive label; matching against any entry catches apps that span several categories, such as a game with a social feed.

Does app blocking map to a recognized security control?

Yes. Application allow and deny lists for managed mobile devices are discussed in NIST SP 800-124 Rev. 2. On Android the policy mechanism is described in the Android Enterprise documentation.

Are the lists suitable for schools?

Many subscribers are schools. US schools and libraries that take E-rate discounts follow the Children's Internet Protection Act, and an app policy is a natural companion to the web filter they already run. A starter list is published at apps to block on school iPads.

Can I contribute to a client library?

Yes. Open an issue or pull request in the language repository. For questions about data or plans, use the contact page.

Links

Related packages

Package Where
appblocklist (Node.js) https://www.npmjs.com/package/appblocklist
appblocklist (Python) https://pypi.org/project/appblocklist/
appblocklist-go, -rust, -java, -dotnet, -php, -ruby, -dart, -elixir https://github.com/explainableaixai

Sister products from Alpha Quantum for the network layer:

License

The client code in this repository and in every appblocklist-* repository is released under the MIT License. Copyright (c) 2026 Alpha Quantum. See LICENSE.

About

Product repo: client for the AppBlockList App Lookup API: filtering categories, age rating and iOS/Android IDs for 1.87M apps

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages