# Packagist Php Packages Scraper (`b2b_lead_generation/packagist-php-packages-scraper`) Actor

Search Packagist PHP packages, track download stats, and analyze vendor libraries. Easily download structured datasets in JSON, CSV, or Excel formats

- **URL**: https://apify.com/b2b_lead_generation/packagist-php-packages-scraper.md
- **Developed by:** [B2B Lead Generation](https://apify.com/b2b_lead_generation) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

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

## Packagist PHP Packages Scraper: PHP packages search and stats

Packagist PHP Packages Scraper collects public PHP package lists, summaries, download counts, and favorites from Packagist. You can search by keyword, look up specific `vendor/package` names, or walk through every package a vendor publishes. The extracted dataset easily exports to JSON, CSV, or Excel formats.

### Use cases

- **PHP package search**: Pull the top Packagist matches for a library name before adding it to composer.json.
- **Download stats**: Compare all-time downloads and favorites for packages you already depend on.
- **Vendor inventory**: List a vendor such as Symfony, then attach the public summary and download total to each package.
- **Type checks**: Keep rows whose Composer type matches `library`, `symfony-bundle`, or another category you specify.
- **Scheduled exports**: Drop the same structured columns into a spreadsheet regularly so package lists stay easy to compare over time.

### Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchQueries` | array | `["laravel"]` | Keywords sent for package search, one per line. Clear the list if you only want named packages or specific vendors. |
| `packageNames` | array | empty | `vendor/package` names to load in detail, including download stats and version details. |
| `vendors` | array | empty | Vendor slugs to collect. Each vendor is listed, and its packages are gathered up to your set cap. |
| `type` | string | empty | Composer type to keep (e.g., `library`). Filtered on package metadata after retrieval. |
| `maxItems` | integer | `100` | Maximum package rows per run (1 to 1000). |
| `requestDelaySecs` | number | `0.3` | Pause between steps to ensure smooth runs. |
| `timeoutSecs` | integer | `300` | Stops starting new tasks after this duration in seconds. |
| `requestTimeoutSecs` | integer | `30` | Timeout per individual request. |

Package names are processed first, followed by vendor lists, and then general search queries. Duplicates are automatically merged so each package appears once.

#### Example input

```json
{
  "searchQueries": ["laravel"],
  "packageNames": ["monolog/monolog"],
  "vendors": [],
  "type": "",
  "maxItems": 100,
  "requestDelaySecs": 0.3,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30
}

```

### Data Output

Each extracted row gives you a clear snapshot of package information. The summary text uses `packageDescription` to keep structured datasets clean and readable.

```json
{
  "name": "laravel/framework",
  "packageDescription": "The Laravel Framework.",
  "url": "[https://packagist.org/packages/laravel/framework](https://packagist.org/packages/laravel/framework)",
  "repository": "[https://github.com/laravel/framework](https://github.com/laravel/framework)",
  "downloads": 593824320,
  "favers": 35448,
  "latestVersion": "",
  "packageType": "",
  "mode": "search",
  "scraped_at": "2026-10-12T00:00:00+00:00"
}

```

Detailed lookups and vendor listings also populate additional fields like `latestVersion`, `packageType`, and `downloadsMonthly` whenever that data is available. If an invalid package name is provided, the run continues smoothly and records the attempt:

```json
{
  "error": "Package not found",
  "input": "not-a-real-vendor/not-a-real-package",
  "status": 404,
  "mode": "detail",
  "scraped_at": "2026-10-12T00:00:00+00:00"
}

```

| Field | Type | Description |
| --- | --- | --- |
| `name` | string | Full package name (`vendor/package`). |
| `packageDescription` | string | Summary description of the package. |
| `url` | string | Web link to the package listing. |
| `repository` | string | Direct link to the source repository. |
| `downloads` | integer | Total all-time download count. |
| `favers` | integer | Number of community favorites/stars on the platform. |
| `latestVersion` | string | Newest release version available. |
| `packageType` | string | Declared Composer type (e.g., library, bundle). |
| `downloadsMonthly` | integer | Monthly download count when available. |
| `mode` | string | Collection mode (`detail`, `vendor`, or `search`). |
| `scraped_at` | string | UTC timestamp of when the row was recorded. |
| `error` | string | Present if an entry could not be retrieved. |
| `input` | string | The requested search term, package, or vendor associated with an error. |
| `status` | integer | Result status code for tracking output status. |

### FAQ

**How fresh are download stats?**
Stats represent current counts at the moment of collection. Search results include overall download counts and favorites, while direct detail lookups break numbers down further into monthly and total figures.

**What happens if a package name is wrong or missing?**
If a specific package name isn't found, it gets saved as an error row in your dataset detailing what failed. The rest of your batch will continue running normally without interruption.

**Why is the summary named packageDescription?**
We use `packageDescription` to ensure column naming remains compatible and consistent across spreadsheet and database exports. The content matches the main summary text of the package.

**Can I export data to CSV or Excel?**
Yes! You can download your completed run data directly as JSON, CSV, or Excel depending on your workflow needs.

#### Trademark Notice

Packagist PHP Packages and related names, logos, and trademarks belong to their respective owners. Their use in this documentation is solely to identify the target topic and does not imply affiliation, sponsorship, endorsement, or official partnership.

#### Disclaimer

This tool is an independent solution and is not officially affiliated with, endorsed by, or sponsored by Packagist or its maintainers. All data is gathered from public sources. Users are responsible for complying with relevant usage terms and licensing requirements.

#### Is web scraping legal?

This scraper collects publicly available information without requiring user accounts or bypassing access controls. Collecting public data is widely practiced, but usage contexts matter:

- **Personal data:** If your results happen to contain personal information (such as personal contributor names or details), local regulations such as GDPR or CCPA may apply. Ensure you handle personal information responsibly and with legitimate purpose.
- **Copyright:** Always ensure you respect copyrighted work such as long-form content or media. Do not republish protected material without permission.
- **Terms & guidelines:** Keep automated requests reasonable, respect community rate limits, and follow standard attribution guidelines.
- **Legal advice:** This documentation provides general operational context and is not legal advice. Consult a legal expert if you have specific regulatory questions.

For more information, feel free to read Apify's helpful overview: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

# Actor input Schema

## `searchQueries` (type: `array`):

Keywords or phrases to send to Packagist search. One query per line. Clear this list if you only want package names or a vendor list.

## `packageNames` (type: `array`):

Composer package names (vendor/name) to load in detail, including download stats and the latest published version.

## `vendors` (type: `array`):

Packagist vendor slugs whose package names should be listed, then loaded one by one until the item cap.

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

Optional Composer package type to keep, such as library or symfony-bundle. Applied after package metadata is loaded. It is not sent as an untested query parameter.

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

Maximum number of package rows to save in one run. The free cap is 1000.

## `requestDelaySecs` (type: `number`):

Seconds to wait between Packagist requests. Minimum 0.3 so the run stays polite.

## `timeoutSecs` (type: `integer`):

Stop starting new requests after this many seconds. Default 300. Maximum 3600.

## `requestTimeoutSecs` (type: `integer`):

Seconds to wait for a single Packagist response before retrying. Default 30.

## `proxyConfiguration` (type: `object`):

Optional proxy for Packagist requests. Leave Apify Proxy off unless an IP is refused.

## Actor input object example

```json
{
  "searchQueries": [
    "laravel"
  ],
  "packageNames": [],
  "vendors": [],
  "type": "",
  "maxItems": 100,
  "requestDelaySecs": 0.3,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `datasetUrl` (type: `string`):

API URL of the default dataset for this run.

## `datasetItemsUrl` (type: `string`):

API URL of the items in the default dataset.

# 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 = {
    "searchQueries": [
        "laravel"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("b2b_lead_generation/packagist-php-packages-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 = {
    "searchQueries": ["laravel"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("b2b_lead_generation/packagist-php-packages-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 '{
  "searchQueries": [
    "laravel"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call b2b_lead_generation/packagist-php-packages-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,b2b_lead_generation/packagist-php-packages-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/zeez06lBuOKZmzJq0/builds/uR7yDjkHRmbTszD1J/openapi.json
