# F-Droid App Catalog Scraper (`datamule/f-droid-scraper`) Actor

Returns open-source Android app metadata from F-Droid: package ID, license, categories, author, source and issue links, version, anti-features, icon and APK URL. Filter by keyword, package ID or category. $0.0005 per app returned (about $0.05 per 100 apps), no API key.

- **URL**: https://apify.com/datamule/f-droid-scraper.md
- **Developed by:** [Datamule](https://apify.com/datamule) (community)
- **Categories:** Developer tools
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 app scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## F-Droid App Catalog Scraper: open-source Android app metadata

Returns structured metadata for open-source Android apps from F-Droid's official public index: package name, license, categories, author, source/issue/changelog links, suggested version, anti-features, icon and APK URL. For developers, license reviewers, researchers and AI agents building app directories or datasets. **Price: $0.0005 per app returned (about $0.05 per 100 apps; lower on paid Apify plans).** No login or API key.

Running it with an empty input `{}` returns the first 100 apps in the catalog (about $0.05).

### Example input

```json
{ "query": "messaging", "categories": ["Internet"], "maxItems": 25 }
```

Other shapes: `{ "packageIds": ["org.fdroid.fdroid"] }` (exact lookup; an F-Droid or Google Play URL also works) or `{ "categories": ["Weather"], "maxItems": 40 }`.

### Example output (real run, description shortened)

```json
{
  "packageName": "InfinityLoop1309.NewPipeEnhanced",
  "name": "PipePipe",
  "summary": "A FLOSS Android app to let you browse YouTube, NicoNico and BiliBili freely.",
  "license": "GPL-3.0-or-later",
  "categories": ["Internet", "Multimedia", "Online Media Player"],
  "authorName": "NullPointerException",
  "webSite": null,
  "sourceCode": "https://github.com/InfinityLoop1308/PipePipe",
  "issueTracker": "https://github.com/InfinityLoop1308/PipePipe/issues",
  "changelog": "https://github.com/InfinityLoop1308/PipePipe/releases",
  "donate": ["https://ko-fi.com/pipepipe"],
  "added": "2023-01-19",
  "lastUpdated": "2026-09-28",
  "suggestedVersionName": "5.4.0",
  "suggestedVersionCode": 110904,
  "antiFeatures": ["NonFreeNet"],
  "iconUrl": "https://f-droid.org/repo/InfinityLoop1309.NewPipeEnhanced/en-US/icon_CWQFN3-pZavxIDWYPYl4GHg-v7k6uCvk6PkmD9S8gSo=.png",
  "latestApkUrl": "https://f-droid.org/repo/InfinityLoop1309.NewPipeEnhanced_110904.apk",
  "url": "https://f-droid.org/packages/InfinityLoop1309.NewPipeEnhanced"
}
```

### Output fields

`packageName`, `name`, `summary`, `description`, `license` (SPDX), `categories`, `authorName`, `webSite`, `sourceCode`, `issueTracker`, `changelog`, `translation`, `donate`, `added` and `lastUpdated` (YYYY-MM-DD), `suggestedVersionName`, `suggestedVersionCode`, `antiFeatures`, `iconUrl`, `latestApkUrl`, `url`. Fields absent for an app are `null`, so the shape is stable.

### Input

| Field | Description |
|---|---|
| `query` | Keyword matched (case-insensitive) against name, summary, description and package ID. |
| `packageIds` | Exact package IDs, F-Droid page URLs or Google Play links. Always returned. |
| `categories` | F-Droid categories, any case; partial names expand (`Games` = every game category). Unknown names return nothing and the log lists valid ones. |
| `maxItems` | Cap on records returned and charged. Default 100. |

Filters combine: an app must match `query` AND any selected category; `packageIds` are always added. The full category list is in the Input tab dropdown (115 categories at last check, e.g. Browser, Messaging, Password & 2FA, Security, VPN & Proxy, Weather).

### Pricing

Pay per event: one `app` event at $0.0005 per app record returned on the Free plan (tiered lower on Bronze to Diamond). Nothing is charged for apps not returned. You can cap spend with Apify's maximum cost per run.

### Limits

- Returns the current snapshot only: no history, change alerts, APK scanning, vulnerability verdicts or install counts.
- Each run downloads the full official index first, then filters, even for a small result.
- A capped run is not a complete catalog: compare the returned count to your `maxItems`.
- Default memory is 256 MB (measured peak about 62 MB at 100 apps; 60-126 MB in earlier larger runs).

### Use from an AI agent / API

Python:

```python
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("datamule/f-droid-scraper").call(
    run_input={"categories": ["Password & 2FA"], "maxItems": 20})
apps = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

MCP (Claude, Cursor and other agents): add `https://mcp.apify.com?tools=datamule/f-droid-scraper` as a remote MCP server with your Apify token. The Actor appears as a tool whose arguments are the Input fields above.

Agent tip: always pass `maxItems`; to look up one app, use `packageIds` only and leave `query` out.

### FAQ

**Why did I get fewer apps than expected?** `query` and `categories` are ANDed. Clear the query to list a whole category.

**Why does `{}` return apps with no filter?** An empty input means "first 100 apps"; pass `maxItems` to change it.

**Is the data live?** It is read from F-Droid's public index at run time.

**Can I export CSV or Excel?** Yes, from the run's dataset in Apify.

**Can I schedule it?** Yes. Schedule the same input and compare `packageName`, `suggestedVersionCode` and `lastUpdated` yourself; the Actor does not store diffs.

# Actor input Schema

## `query` (type: `string`):

Optional keyword, case-insensitive, matched against app name, summary, description and package ID. Combines with categories (both must match). Leave empty to skip. Example: "messaging".

## `packageIds` (type: `array`):

Optional exact Android package IDs to fetch; always returned regardless of query/categories. You can paste an F-Droid app page URL or a Google Play link instead of an ID. Example: \["org.fdroid.fdroid", "org.thoughtcrime.securesms"].

## `categories` (type: `array`):

Optional F-Droid categories; an app matches if it is in any of them. Case-insensitive; a partial name expands ("Games" = all game categories). An unmatched name returns nothing for it and the log lists valid names. Example: \["Security", "Password & 2FA"].

## `maxItems` (type: `integer`):

Maximum app records to return and be charged for (1 or more). Default 100 (about $0.05). The full catalog is several thousand apps, so raise it deliberately. Example: 25.

## Actor input object example

```json
{
  "query": "messaging",
  "packageIds": [
    "org.fdroid.fdroid",
    "org.thoughtcrime.securesms"
  ],
  "categories": [
    "Security",
    "Password & 2FA"
  ],
  "maxItems": 25
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "query": "messaging",
    "packageIds": [],
    "categories": [],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamule/f-droid-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "query": "messaging",
    "packageIds": [],
    "categories": [],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("datamule/f-droid-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": "messaging",
  "packageIds": [],
  "categories": [],
  "maxItems": 100
}' |
apify call datamule/f-droid-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datamule/f-droid-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/DQyRL1cLNpGzP3rUF/builds/WVKnFBknZQQ3j5SfG/openapi.json
