# WordPress Plugin Scraper - Installs & Ratings (`dataio/wordpress-org-plugin-stats`) Actor

Scrape WordPress.org plugin data: active installs, rating with its full review distribution, support resolution rate computed, compatibility checked against the current WordPress release, and days since the last update. Search by keyword or plugin slug. No API key.

- **URL**: https://apify.com/dataio/wordpress-org-plugin-stats.md
- **Developed by:** [Tom Awake](https://apify.com/dataio) (community)
- **Categories:** Developer tools, E-commerce, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 plugins

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

### What does WordPress Plugin Scraper do?

The **68,589 plugins** in the WordPress directory, with what actually
decides whether to install one: how many sites run it, whether anyone
still maintains it, and whether its support answers.

The directory publishes all of that, scattered. A support resolution rate
you have to compute. A compatibility figure expressed as a version number
you have to compare against the current WordPress release. A rating out of
100 when the interface shows five stars.

No API key. No account.

***

### The number nobody computes

The directory reports "48 support threads, 36 resolved" and never the
ratio. It is the best available answer to the question that matters when
something breaks at 2am on a client site.

Measured across 300 popular plugins, 112 had enough support activity to
judge — and the spread is not subtle:

| Plugin | Resolved | Threads | Active installs |
|---|---|---|---|
| **WPS Hide Login** | **0%** | 0 / 6 | **2,000,000** |
| … | | | |
| Elementor | 75% | 36 / 48 | 10,000,000 |

Two million sites running a plugin whose support has resolved nothing.
That is not visible anywhere on its directory page.

***

### The four things this does that the source does not

**1. The support resolution rate.**

`supportResolutionPct`, alongside the raw counts so you can see whether
the rate rests on six threads or six hundred.

**2. Obsolescence, dated and qualified.**

`tested` says which WordPress version a plugin was verified against. The
Actor fetches the **current** WordPress release at runtime and compares —
so `isOutdated` stays correct as WordPress ships, instead of being frozen
against a constant that ages. `daysSinceUpdate` carries the other half.

**3. Downloads per install.**

Elementor: 10,000,000 active installs, 887,457,954 downloads — **88.7 per
site**. That ratio is the update cadence. A very low one means a plugin
people install once and never update, which is its own kind of risk.

**4. The rating as stars, with the distribution behind it.**

90/100 becomes 4.5 stars, and `ratings1` through `ratings5` show what it
is made of. Elementor's 4.5 rests on 6,145 five-star reviews and 684
one-star ones — a shape the single number hides. `hasEnoughRatings` flags
anything resting on fewer than 50.

***

### Field coverage

Measured on 300 popular plugins.

| Field | Coverage |
|---|---|
| `name`, `activeInstalls`, `totalDownloads` | 100% |
| `ratingStars`, `ratingCount`, review distribution | 100% |
| `lastUpdated`, `ageYears`, `testedUpTo`, `requiresPhp` | 100% |
| `downloadsPerInstall` | 100% |
| `daysSinceUpdate` | 98% |
| `homepage` | 93% |
| `supportThreads` | 87% |
| `supportResolutionPct` | 69% |

`supportResolutionPct` is empty where a plugin has no support threads at
all — no activity, no rate. That is an absence, not a gap, and it is left
empty rather than reported as zero.

***

### What it is for

- **Choosing a plugin for a client site.** Installs, rating shape, support
  resolution and last update in one table, for every candidate.
- **Auditing an existing site.** Feed in the slugs a site runs and see
  which ones stopped being maintained.
- **Competitive research.** A competitor's whole catalogue by author, with
  adoption and support quality per plugin.
- **Finding a gap.** Search a category, sort by installs, and look for
  plugins with large user bases, poor support and no recent release.
- **Acquisition screening.** Plugins with real adoption and an absent
  maintainer are the ones that get bought.

Three dataset views ship with the Actor: **Plugins**, **Support quality**
and **Maintenance risk**.

***

### Limits

Stated plainly, because they affect what you can conclude.

- **Active installs are bucketed, not exact.** WordPress reports
  10,000,000 or 90,000 — rounded figures, not counts. Treat them as
  orders of magnitude.
- **Support threads count the last two months only.** A plugin with six
  threads is not a plugin with six problems ever; it is a snapshot of
  recent activity, and small numbers make an unreliable rate.
- **Reviews are cumulative and never expire.** A plugin that was bad in
  2019 and good since still carries those one-star reviews. Read the
  distribution alongside `ageYears`.
- **`isOutdated` is a heuristic.** Plugins are marked untested when they
  lag the current release by roughly two major versions. A plugin can be
  perfectly functional and simply not re-tested.
- **Directory plugins only.** Premium and commercial plugins distributed
  outside wordpress.org — a large part of the real market — are not here
  at all.
- **`downloadsPerInstall` is not a ratio of people.** Downloads include
  every automatic update, mirror and CI fetch.
- **Search is the directory's own.** Relevance ordering is WordPress's,
  and it is not the same as ordering by quality or adoption.

***

### How much does it cost?

You pay per plugin returned: **$0.003 each**, that is $3.00 per 1,000. There is no start fee, and subscription plans pay less per plugin.

The example input below asks for up to 500 plugins, so it costs **$1.50 at most**.

If a run reaches the spending limit you set, the output stops at that limit and never goes past it. You are never charged for rows that were not delivered.

### Use WordPress Plugin Scraper as an API

Call it from your own code with the Apify client, here in Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("DataIO/wordpress-org-plugin-stats").call(run_input={
    'browse': 'popular',
    'minActiveInstalls': 10000,
    'maxItems': 500,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

It also works from JavaScript, Make, Zapier, n8n, and from AI agents through the Apify MCP server.

### Other actors you might like

- [npm Downloads Scraper](https://apify.com/DataIO/npm-registry-download-trends): Package Trends & Growth
- [crt.sh Subdomain Finder](https://apify.com/DataIO/crtsh-subdomain-finder): Certificate Search
- [Domain Expiry Checker](https://apify.com/DataIO/rdap-domain-expiry-monitor): RDAP Registrar & Status

### FAQ

#### Is it legal to use this data?

The actor reads public data from its official source, without logging in and without bypassing any access control. What you do with the data, for example contacting people listed in it, is your responsibility under the laws that apply to you, such as GDPR in Europe.

#### Can I run it on a schedule?

Yes. Create a schedule in Apify Console, daily or weekly for example, and each run delivers a fresh dataset, which you can send by email, webhook or integration.

#### Can AI agents use it?

Yes. It is available through the Apify MCP server, and every input field is described in its input schema, so an agent can call it directly.

### Source

The public [WordPress.org plugin
API](https://api.wordpress.org/plugins/info/1.2/), the same endpoint
behind the plugin browser in every WordPress install, plus the core
version-check API for the current release. No authentication. This Actor
is not affiliated with WordPress.org or Automattic.

# Actor input Schema

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

Keyword, as a user would search the plugin directory: seo, backup, forms, cache, membership.

## `slugs` (type: `array`):

Exact slugs from the directory URL — woocommerce from wordpress.org/plugins/woocommerce/. Use this to track a fixed set of competitors.

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

Used when no search term or slug is given. Popular is the top of the directory by active installs.

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

WordPress.org username. Returns that author's whole catalogue — the fastest way to see everything a competitor ships.

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

Directory tag, for example ecommerce, security, gutenberg.

## `minActiveInstalls` (type: `integer`):

10000 removes most of the long tail. The directory holds 68,589 plugins and the great majority have almost no adoption.

## `minRating` (type: `integer`):

Check ratingCount alongside: a 4.5 built on twelve reviews is not a 4.5.

## `minSupportResolutionPct` (type: `integer`):

The share of support threads marked resolved. This is the field that tells you what happens when something breaks, and the directory never shows it as a rate.

## `updatedWithinDays` (type: `integer`):

Removes abandoned plugins. 365 is generous; an actively maintained plugin ships every few weeks.

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

One row per plugin, sorted by active installs.

## Actor input object example

```json
{
  "browse": "popular",
  "maxItems": 500
}
```

# Actor output Schema

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

Every row produced by the run, in JSON.

# 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 = {
    "maxItems": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataio/wordpress-org-plugin-stats").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 = { "maxItems": 500 }

# Run the Actor and wait for it to finish
run = client.actor("dataio/wordpress-org-plugin-stats").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 '{
  "maxItems": 500
}' |
apify call dataio/wordpress-org-plugin-stats --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataio/wordpress-org-plugin-stats"
        }
    }
}
```

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/QluxtctJh42lp41hO/builds/dr8sPMhM6hQa94fQB/openapi.json
