# Swift Package Index Scraper (`crawlerbros/swift-package-index-scraper`) Actor

Scrape the Swift Package Index (swiftpackageindex.com) - search packages, look up rich package details or CI build matrices, list every package by a GitHub author/org, browse by keyword or SSWG maturity collection, pull recently added packages or releases, or list the entire package catalog.

- **URL**: https://apify.com/crawlerbros/swift-package-index-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Developer tools, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Swift Package Index Scraper

Scrape the [Swift Package Index](https://swiftpackageindex.com) — the community catalog of open-source Swift packages. Search packages by keyword, pull a rich package detail page or its full CI build matrix, list every package published by a GitHub author or organization, browse packages by keyword/tag or by Swift Server Work Group (SSWG) maturity level, track recently added packages or releases, or list the entire package catalog in one run.

No login, no API key, and no cookies required — every mode reads data that is publicly visible on swiftpackageindex.com.

### What this actor does

- **Search** packages by free-text query (name, description, keywords), with support for the site's built-in filter tokens (`stars:>500`, `platform:ios,linux`, `product:plugin`, etc.)
- **Package detail** — full metadata for one exact `owner/repo` package: summary, license, stars, Swift-tool and platform compatibility, SSWG collection membership, dependency/build stats, keywords, homepage and documentation links
- **Package build matrix** — the full CI build results for one exact `owner/repo` package: pass/fail status for every Swift version × platform × package version combination the site has tested, with a direct link to each build's log page
- **By author/org** — every package published under a GitHub username or organization (e.g. every package from `vapor`, `apple`, `pointfreeco`)
- **By keyword/tag** — every package tagged with a given keyword (e.g. `server`, `networking`, `swiftui`)
- **By SSWG collection** — browse the three official [Swift Server Work Group](https://www.swift.org/sswg/) maturity tiers: Sandbox, Incubating, Graduated
- **Recently added packages** — the newest packages indexed by the site
- **Recent releases** — the newest package releases, filterable by release kind (major / minor / patch / pre-release) and including changelog notes
- **Full package catalog** — every package the site has ever indexed (~11,000+), each with its last-updated date, straight from the site's sitemap index — the only unscoped, non-time-limited way to enumerate the entire catalog
- Empty fields are always omitted — every record only contains data that was actually found

### Output per record

Every record is a flat JSON object. Fields are only present when the source page/feed actually contains that data — this actor never emits `null`, empty strings, or placeholder values.

| Field | Description |
|---|---|
| `owner` | GitHub user/org that owns the package |
| `repo` | GitHub repository name |
| `packageName` | Display name of the package |
| `summary` | Short package description |
| `githubUrl` | GitHub repository URL |
| `packageUrl` | Swift Package Index page URL |
| `licenseName` / `licenseUrl` | Package license (e.g. `MIT`) and link to the license file |
| `readmeUrl` | Direct link to the package's README on GitHub |
| `latestVersion` / `stableVersion` | Most recent stable release version |
| `betaVersion` | Most recent beta/pre-release version, if any |
| `defaultBranch` | Name of the default Git branch |
| `versionCount` | Number of published versions indexed |
| `swiftToolsVersion` | Swift tools version declared by the latest manifest |
| `compatibleSwiftVersions[]` | Swift language versions the latest release builds against |
| `compatiblePlatforms[]` | Apple/Linux/Android/Wasm platforms the latest release builds for |
| `keywords[]` | Tags/keywords associated with the package |
| `matchingKeywords[]` | *(search mode)* keywords that matched the search query |
| `starCount` | GitHub star count |
| `hasDocumentation` | *(search mode)* whether hosted documentation is available |
| `lastActivity` | *(search mode)* human-readable recency of the last commit/release |
| `maintainerInfo` | Free-text maintainer/ownership description |
| `developmentSummary` / `commitsCount` / `releasesCount` | *(packageDetail)* development history stats |
| `activitySummary` / `openIssuesCount` / `openPullRequestsCount` | *(packageDetail)* GitHub issue/PR activity |
| `dependenciesSummary` / `dependenciesCount` | *(packageDetail)* number of dependency packages |
| `librariesCount` / `executablesCount` / `pluginsCount` / `macrosCount` | *(packageDetail)* product counts by type |
| `sswgCollectionSlug` / `sswgCollectionName` | *(packageDetail)* SSWG maturity collection membership, if any |
| `products[]` | *(packageDetail)* every library/executable/plugin/macro product the package vends, with its `name` and `type` |
| `dataRaceSafetySummary` | *(packageDetail)* Swift 6 strict-concurrency status, e.g. `Zero data race safety errors` |
| `dataRaceSafetyErrorCounts` | *(packageDetail)* per-platform data-race error counts (e.g. `{"iOS": 0, "Linux": 0}`), when the site publishes a breakdown |
| `fundingText` | *(packageDetail)* sponsorship/funding blurb, if the maintainer has one configured |
| `firstPublishedAt` | *(packageDetail)* ISO-8601 UTC timestamp the package was first published |
| `homepageUrl` / `documentationUrl` | *(packageDetail)* package homepage and hosted documentation links |
| `lastUpdated` | *(packageDetail, allPackages)* ISO date the package's page was last refreshed |
| `version` | *(recentReleases)* the released version string |
| `releasedAt` / `addedAt` | ISO-8601 UTC timestamp of the release/addition |
| `changelogNotes` | *(recentReleases)* changelog/release-notes text, if published |
| `swiftVersion` | *(packageBuilds)* Swift language version the build was run under, e.g. `6.3` |
| `platform` | *(packageBuilds)* target platform of the build, e.g. `macOS (SPM)`, `iOS`, `Linux`, `Wasm`, `Android` |
| `packageVersion` | *(packageBuilds)* package version/branch the build was run against |
| `versionKind` | *(packageBuilds)* `stable`, `beta`, or `branch` — which release channel `packageVersion` represents |
| `buildStatus` | *(packageBuilds)* `succeeded` or `failed` |
| `buildUrl` | *(packageBuilds)* link to the individual build's log page |
| `hasGeneratedDocs` | *(packageBuilds)* whether this specific build generated hosted documentation |
| `recordType` | `package`, `packageDetail`, `build`, or `release` |
| `scrapedAt` | UTC ISO timestamp of when the actor collected the record |

### Input

| Field | Type | Applies to mode | Default | Description |
|---|---|---|---|---|
| `mode` | select | — | `byAuthor` | Which lookup to run — see the mode table below |
| `searchQuery` | string | `search` | `vapor` | Free-text query, optionally with filter tokens like `stars:>500` |
| `packageOwner` | string | `packageDetail`, `packageBuilds` | `vapor` | GitHub user/org that owns the package |
| `packageRepo` | string | `packageDetail`, `packageBuilds` | `vapor` | GitHub repository name of the package |
| `authorName` | string | `byAuthor` | `vapor` | GitHub user/org to list every indexed package for |
| `keyword` | string | `byKeyword` | `server` | Keyword/tag slug to list every package tagged with it |
| `collectionSlug` | select | `byCollection` | `sswg-graduated` | `sswg-sandbox` / `sswg-incubating` / `sswg-graduated` |
| `releaseMajor` | boolean | `recentReleases` | `true` | Include major-version releases |
| `releaseMinor` | boolean | `recentReleases` | `true` | Include minor-version releases |
| `releasePatch` | boolean | `recentReleases` | `true` | Include patch-version releases |
| `releasePre` | boolean | `recentReleases` | `false` | Include pre-release / beta / alpha versions |
| `maxItems` | integer | all | `50` | Hard cap on the number of records emitted (1–1000) |

#### Modes

| Mode | What it returns |
|---|---|
| `search` | Packages matching a free-text search query, newest-ranked-first, paginated |
| `packageDetail` | One record with the full detail page for an exact `packageOwner`/`packageRepo` |
| `packageBuilds` | One record per Swift-version/platform/package-version build cell for an exact `packageOwner`/`packageRepo` |
| `byAuthor` | Every package published by a GitHub user/org |
| `byKeyword` | Every package tagged with a keyword |
| `byCollection` | Every package in an SSWG maturity collection |
| `recentPackages` | The most recently added packages, newest first |
| `recentReleases` | The most recent releases across all indexed packages, newest first |
| `allPackages` | Every package in the full catalog (owner/repo + last-updated date), unscoped and not time-limited |

#### Example: search for networking packages

```json
{
  "mode": "search",
  "searchQuery": "networking",
  "maxItems": 30
}
```

#### Example: full detail for one package

```json
{
  "mode": "packageDetail",
  "packageOwner": "vapor",
  "packageRepo": "vapor"
}
```

#### Example: build matrix for one package

```json
{
  "mode": "packageBuilds",
  "packageOwner": "vapor",
  "packageRepo": "vapor"
}
```

#### Example: every package by an organization

```json
{
  "mode": "byAuthor",
  "authorName": "pointfreeco",
  "maxItems": 100
}
```

#### Example: browse the graduated SSWG collection

```json
{
  "mode": "byCollection",
  "collectionSlug": "sswg-graduated"
}
```

#### Example: recent stable releases only (no pre-releases)

```json
{
  "mode": "recentReleases",
  "releaseMajor": true,
  "releaseMinor": true,
  "releasePatch": true,
  "releasePre": false,
  "maxItems": 100
}
```

#### Example: full package catalog

```json
{
  "mode": "allPackages",
  "maxItems": 500
}
```

### Use cases

- **Dependency research** — check a Swift package's license, Swift-tools version, and platform compatibility before adding it to a project
- **Ecosystem monitoring** — track new packages and releases across the whole Swift open-source community as they're published
- **Server-side Swift adoption** — browse the SSWG Sandbox/Incubating/Graduated tiers to find production-ready server packages
- **CI/build health audits** — pull a package's full build matrix to see which Swift versions and platforms it currently passes on
- **Author/organization audits** — list every package a company or maintainer publishes, e.g. Vapor, Apple, PointFree
- **Catalog-wide analytics** — export the entire Swift Package Index catalog to analyze ecosystem trends over time

### FAQ

**Do I need a Swift Package Index account or API key?**
No. Every mode reads publicly available pages and feeds — no login, API key, or cookies are needed.

**Why do some records have fewer fields than others?**
`packageDetail` reads the richest, most complete data (a single package's full page). `byAuthor`/`byKeyword`/`byCollection` read a lighter public JSON feed that doesn't include GitHub star counts or issue/PR activity. `search` and `recentPackages`/`recentReleases` each expose whatever their respective page/feed publishes. Fields that a given mode can't populate are simply omitted rather than sent as empty or fake values.

**Can I filter recent releases to only stable versions?**
Yes — set `releaseMajor`/`releaseMinor`/`releasePatch` to `true` and `releasePre` to `false` to exclude pre-releases. Note that if all four toggles are left off, the Swift Package Index feed falls back to showing every release kind (this is upstream behavior, not a bug).

**Does `search` support the site's advanced filter syntax?**
Yes — anything you could type into the search box on swiftpackageindex.com (e.g. `stars:>500`, `last_activity:>2024-01-01`, `platform:ios,linux`, `product:plugin`) works in `searchQuery` since it's passed straight through.

**How many packages can I fetch in one run?**
Use `maxItems` (1–1000) to cap how many records are emitted. `byKeyword` and `byCollection` return their full result set in one response; `search` and `recentPackages`/`recentReleases` paginate until `maxItems` is reached or the source runs out of results.

**What's the difference between `allPackages` and `byAuthor`/`byKeyword`/`byCollection`?**
`allPackages` is the entire, unscoped catalog — every package the site has ever indexed, in one list — while `byAuthor`/`byKeyword`/`byCollection` are scoped to a single author, tag, or SSWG tier. `allPackages` records only carry `owner`, `repo`, `packageName`, `lastUpdated`, and the two URL fields (no summary/license/stars); run `packageDetail` on a specific `owner`/`repo` from the results for the richer fields.

**Why might `search`, `packageDetail`, `packageBuilds`, or `allPackages` occasionally return 0 results or fewer fields than expected?**
These four modes read swiftpackageindex.com's web pages, which very occasionally throttle a request. On the rare run where that happens the actor reports it with a clear status message — simply re-run. `byAuthor`, `byKeyword`, `byCollection`, `recentPackages`, and `recentReleases` read public data feeds instead and aren't affected.

**Is this affiliated with Apple or the Swift project?**
No. The Swift Package Index is an independent, community-run, open-source project. This actor is an independent scraper of its publicly available pages and feeds.

# Actor input Schema

## `mode` (type: `string`):

What to fetch from the Swift Package Index.

## `searchQuery` (type: `string`):

Free-text query, e.g. `vapor`, `networking`, `swiftui charts`. You can also add filter tokens such as `stars:>500` or `platform:ios,linux` — see the Swift Package Index search FAQ.

## `packageOwner` (type: `string`):

GitHub user or organization that owns the package, e.g. `vapor`.

## `packageRepo` (type: `string`):

GitHub repository name of the package, e.g. `vapor`.

## `authorName` (type: `string`):

GitHub user or organization name to list every indexed package for, e.g. `vapor`, `apple`, `pointfreeco`.

## `keyword` (type: `string`):

Keyword (tag) slug to list every package tagged with it, e.g. `server`, `networking`, `swiftui`.

## `collectionSlug` (type: `string`):

Swift Server Work Group package maturity collection to browse.

## `releaseMajor` (type: `boolean`):

Include major-version releases (e.g. 1.0.0 → 2.0.0) in the recent-releases feed.

## `releaseMinor` (type: `boolean`):

Include minor-version releases (e.g. 1.0.0 → 1.1.0) in the recent-releases feed.

## `releasePatch` (type: `boolean`):

Include patch-version releases (e.g. 1.0.0 → 1.0.1) in the recent-releases feed.

## `releasePre` (type: `boolean`):

Include pre-release / beta / alpha versions (e.g. 2.0.0-beta.1) in the recent-releases feed. Note: the Swift Package Index feed falls back to showing every release kind if all four release-kind toggles are left off.

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

Hard cap on the number of records emitted in one run.

## Actor input object example

```json
{
  "mode": "byAuthor",
  "searchQuery": "vapor",
  "packageOwner": "vapor",
  "packageRepo": "vapor",
  "authorName": "vapor",
  "keyword": "server",
  "collectionSlug": "sswg-graduated",
  "releaseMajor": true,
  "releaseMinor": true,
  "releasePatch": true,
  "releasePre": false,
  "maxItems": 20
}
```

# Actor output Schema

## `packages` (type: `string`):

Dataset containing all scraped Swift Package Index records.

# 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 = {
    "mode": "byAuthor",
    "searchQuery": "vapor",
    "packageOwner": "vapor",
    "packageRepo": "vapor",
    "authorName": "vapor",
    "keyword": "server",
    "collectionSlug": "sswg-graduated",
    "releaseMajor": true,
    "releaseMinor": true,
    "releasePatch": true,
    "releasePre": false,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/swift-package-index-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 = {
    "mode": "byAuthor",
    "searchQuery": "vapor",
    "packageOwner": "vapor",
    "packageRepo": "vapor",
    "authorName": "vapor",
    "keyword": "server",
    "collectionSlug": "sswg-graduated",
    "releaseMajor": True,
    "releaseMinor": True,
    "releasePatch": True,
    "releasePre": False,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/swift-package-index-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 '{
  "mode": "byAuthor",
  "searchQuery": "vapor",
  "packageOwner": "vapor",
  "packageRepo": "vapor",
  "authorName": "vapor",
  "keyword": "server",
  "collectionSlug": "sswg-graduated",
  "releaseMajor": true,
  "releaseMinor": true,
  "releasePatch": true,
  "releasePre": false,
  "maxItems": 20
}' |
apify call crawlerbros/swift-package-index-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/swift-package-index-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/mycWVCKbh69JCfsIF/builds/Rr5r0cg2AShkyloK1/openapi.json
