# WordPress Plugin Detector: Plugins, Versions & WooCommerce (`centorprat/wordpress-plugin-detector`) Actor

Lists every plugin a WordPress site runs (with versions), checks each against wordpress.org (outdated, abandoned, or removed for security), plus theme, WordPress version, WooCommerce products/payments and hosting. Bulk URLs or a dataset.

- **URL**: https://apify.com/centorprat/wordpress-plugin-detector.md
- **Developed by:** [Centor Prat](https://apify.com/centorprat) (community)
- **Categories:** Developer tools, Lead generation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.25 / 1,000 site profileds

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/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

## WordPress Plugin Detector: Plugins, Versions & WooCommerce

**Paste websites and see every plugin each WordPress site runs**, with versions, checked against the official
wordpress.org directory. You see which plugins are **outdated**, which haven't been updated in two years, and
which were **removed from wordpress.org** (with the reason, e.g. "Security Issue"). You also get the theme, the
WordPress version and how far behind it is, **WooCommerce store facts** (products, currency, payment gateways),
hosting, and a short list of findings to pitch. Non-WordPress sites are skipped for free.

Built for **WordPress maintenance and security agencies** ("your site runs 6 outdated plugins and one pulled
for a security issue"), **plugin and SaaS vendors** (find sites on a competitor's plugin), and **WooCommerce
service providers** (stores, their size and their payment stack).

### ⚡ How it works

1. **Asset paths:** every `/wp-content/plugins/<slug>/...?ver=<version>` the pages load gives the plugin and,
   usually, its version.
2. **REST index:** the public `/wp-json/` lists the namespaces plugins register (WooCommerce, Yoast, Elementor,
   Gravity Forms, LearnDash...), which catches plugins that load nothing on the page.
3. **wordpress.org Plugins API:** each slug gets its real name, latest version, active installs, rating and last
   update, or the closure notice (date + reason) if the plugin was removed. 60+ premium plugins (Elementor Pro, WP
   Rocket, Gravity Forms, WPML, WooCommerce Subscriptions...) are named from a built-in list.
4. **Theme** from the theme's `style.css` header (name, version, author, parent), **WordPress version** from
   core-versioned assets or the RSS generator (never from jQuery's `?ver=`), compared with the latest release.
5. **WooCommerce:** the public Store API gives the product count and currency; payment-gateway plugins are listed.
6. **Hosting / CDN** from response headers and host-specific plugins (WP Engine, Kinsta, SiteGround, Cloudflare,
   WordPress VIP...), never from page text.

### 📋 What you get (per WordPress site)

| Field | What it is |
|---|---|
| `plugins` | `name`, `slug`, `category`, `detectedVersion`, `latestVersion`, `activeInstalls`, `rating`, `lastUpdated`, `outdated`, `abandoned`, `closed` + `closedReason`, `evidence` |
| `pluginsByCategory` | ecommerce, payments, seo, performance, security, backup, forms, pageBuilder, marketing, analytics, privacy, multilingual, membership, lms, booking, events, media, social, developer... |
| `outdatedPlugins`, `abandonedPlugins`, `closedPlugins` | The ones to fix (closed = removed from wordpress.org, no more updates) |
| `wordpress` | `version`, `latest`, `releasesBehind`, `outdated` (2+ major releases behind) |
| `theme` | `slug`, `name`, `version`, `author`, `parent` |
| `woocommerce` | `isWooCommerce`, `productsCount`, `currency`, `paymentPlugins`, `storeApiOpen` |
| `hosting` | WP Engine, Kinsta, SiteGround, Cloudflare, WordPress VIP, GoDaddy, Bluehost... |
| `findings`, `pitch` | Scored findings: removed plugins, outdated plugins, abandoned plugins, old WordPress, no caching / security / SEO / backup plugin |

### 📥 Input

| Field | What it does |
|---|---|
| `urls` | Websites or domains |
| `datasetId` | Any dataset with a website / url / domain field (Google Maps run, lead list, store finder...) |
| `requirePlugins` | Keep sites using any of these, e.g. `["woocommerce"]`, `["elementor"]` |
| `excludePlugins` | Drop sites using any of these (e.g. your own plugin) |
| `onlyWithIssues` | Only sites with outdated / removed plugins or WordPress 2+ releases behind |
| `onlyWooCommerce` | Only WooCommerce stores |
| `includeNonWordPress` | Also return (unbilled) rows for non-WordPress or unreadable sites |

**Example: maintenance prospects from a Google Maps search**

```json
{ "datasetId": "<your Google Maps scraper dataset>", "onlyWithIssues": true }
```

**Example: WooCommerce stores not on your payment plugin**

```json
{ "urls": ["store-one.com", "store-two.com"], "onlyWooCommerce": true, "excludePlugins": ["woocommerce-payments"] }
```

### 📤 Output (one row per site, shortened)

```json
{
  "siteName": "WooCommerce",
  "url": "https://woocommerce.com",
  "wordpress": {"version": "7.1.3", "latest": "7.1.3", "releasesBehind": 0, "outdated": false},
  "theme": {"slug": "refer-wordpress", "parent": "woo"},
  "pluginsCount": 7,
  "plugins": [
    {"slug": "woocommerce", "name": "WooCommerce", "category": "ecommerce", "latestVersion": "11.2.1",
     "activeInstalls": 7000000, "rating": 90, "lastUpdated": "2026-10-09",
     "evidence": "asset path /wp-content/plugins/woocommerce/"},
    {"slug": null, "name": "Gravity Forms", "category": "forms", "evidence": "REST namespace gf/v2"}
  ],
  "pluginsByCategory": {"ecommerce": ["WooCommerce", "WooPayments"], "forms": ["Gravity Forms"],
                        "seo": ["Yoast SEO"], "security": ["Akismet"], "suite": ["Jetpack"]},
  "outdatedPlugins": [],
  "closedPlugins": [],
  "woocommerce": {"isWooCommerce": true, "productsCount": 1759, "currency": "USD", "paymentPlugins": ["WooPayments"]},
  "hosting": ["WordPress.com VIP / Automattic"],
  "pitch": ["No backup plugin visible (may be handled by the host)"]
}
```

A plugin removed from the directory looks like this:

```json
{"name": "Display Widgets", "closed": true, "closedDate": "2021-01-30", "closedReason": "Security Issue"}
```

### 💰 Pricing (pay-per-event)

- **Site profiled: $0.005** per WordPress site ($5 per 1,000).
- Free: non-WordPress sites and sites that can't be read.
- Filters run after the profile, so every profiled WordPress site is billed.

### 💡 Use cases

- **Maintenance & care-plan agencies:** prospects with outdated or removed plugins and old WordPress, plus the exact list to quote.
- **Security agencies:** sites running plugins pulled from wordpress.org for security issues.
- **Plugin vendors:** sites on a competitor's plugin (`requirePlugins`), and sites missing your category (no SEO, caching or security plugin).
- **WooCommerce services:** store size, currency and payment stack for payment, shipping or marketing providers.
- **Hosting companies:** sites on a given host or with no caching layer (migration pitch).

### 🚀 Ready-made tasks

- [WordPress Plugin Detector](https://apify.com/centorprat/wordpress-plugin-detector/examples/wordpress-plugin-detector-bulk)
- [Outdated WordPress Plugins Checker](https://apify.com/centorprat/wordpress-plugin-detector/examples/outdated-wordpress-plugins-checker)
- [WooCommerce Store Detector (Products & Payments)](https://apify.com/centorprat/wordpress-plugin-detector/examples/woocommerce-store-detector)

### 🔌 API, Standby and agents

```bash
curl "https://centorprat--wordpress-plugin-detector.apify.actor/?url=woocommerce.com&token=<YOUR_APIFY_TOKEN>"
```

```python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("centorprat/wordpress-plugin-detector").call(run_input={"urls": ["woocommerce.com"]})
for s in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(s["url"], s["pluginsCount"], s["outdatedPlugins"], s["closedPlugins"])
```

**MCP:** `https://mcp.apify.com/?tools=actors,docs,centorprat/wordpress-plugin-detector`

### ❓ FAQ

**Can it see every plugin?** It sees plugins that load assets on the pages it reads or register a REST namespace,
which is most plugins with front-end features. Admin-only plugins with no public trace can't be seen.

**How reliable is "outdated"?** The version comes from the plugin's own `?ver=` asset parameter, which almost all
plugins set to their version. Values equal to the WordPress version or that look like timestamps are ignored.
Treat `outdated` as a strong signal, and confirm before quoting.

**What does "closed" mean?** wordpress.org removed the plugin from the directory. It gets no more updates. The
reason is shown (security issue, guideline violation, author request...).

**Is the WordPress version always found?** When the site exposes it (generator tag, core asset versions or RSS
feed). Hardened sites hide it, and then `version` is null.

**Is it legal?** It reads public pages, the public REST index and the public wordpress.org API. No login, no
scanning, no exploit attempts.

### 📜 Data & attribution

Public website pages and REST endpoints, plus the public wordpress.org Plugins API. Plugin and theme names belong
to their authors.

### 🔗 Related actors

- [Shopify App Detector: Tech Stack, Pixels & Theme](https://apify.com/centorprat/shopify-app-detector): every app a Shopify store runs, with evidence, estimated app spend and change tracking.
- [Domain Lookup API - DNS, MX, SPF, Tech & Contact Emails](https://apify.com/centorprat/domain-lookup-dns-mx-email): DNS + live homepage → IPs, MX/SPF, tech, socials and public contacts per domain.
- [Google Maps Leads + Website Audit for Agencies](https://apify.com/centorprat/google-maps-leads-website-audit): local businesses from Google Maps audited for website, Google profile, reviews, booking and tracking gaps.

# Actor input Schema

## `urls` (type: `array`):

Websites or domains, e.g. \["woocommerce.com", "wpbeginner.com"]. Non-WordPress sites are skipped for free.

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

Pick any dataset with a website / url / domain field (a Google Maps scraper run, a lead list, a store finder...). Read-only.

## `requirePlugins` (type: `array`):

e.g. \["woocommerce"], \["elementor"], \["Yoast SEO", "Rank Math"]. Matches plugin names or slugs, case-insensitive.

## `excludePlugins` (type: `array`):

e.g. your own plugin, to keep only prospects.

## `onlyWithIssues` (type: `boolean`):

Return only sites with at least one outdated plugin, a plugin removed from wordpress.org, or WordPress 2+ major releases behind. Built for maintenance and security agencies.

## `onlyWooCommerce` (type: `boolean`):

Return only WordPress sites running WooCommerce.

## `includeNonWordPress` (type: `boolean`):

Adds an unbilled row for each site that isn't WordPress or couldn't be read.

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

Safety cap when reading a dataset.

## `concurrency` (type: `integer`):

How many sites are profiled at once.

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

If set, the results are POSTed here as JSON.

## Actor input object example

```json
{
  "urls": [
    "woocommerce.com",
    "wpbeginner.com",
    "yoast.com"
  ],
  "onlyWithIssues": false,
  "onlyWooCommerce": false,
  "includeNonWordPress": false,
  "maxItems": 2000,
  "concurrency": 6
}
```

# Actor output Schema

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

One row per WordPress site: plugins (name, slug, category, detected version, latest version, active installs, last update, outdated / abandoned / closed with reason, evidence), plugins by category, theme, WordPress version and releases behind, WooCommerce facts (products, currency, payment plugins), hosting, findings with scores and pitch lines.

# 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 = {
    "urls": [
        "woocommerce.com",
        "wpbeginner.com",
        "yoast.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("centorprat/wordpress-plugin-detector").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 = { "urls": [
        "woocommerce.com",
        "wpbeginner.com",
        "yoast.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("centorprat/wordpress-plugin-detector").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 '{
  "urls": [
    "woocommerce.com",
    "wpbeginner.com",
    "yoast.com"
  ]
}' |
apify call centorprat/wordpress-plugin-detector --silent --output-dataset

```

## MCP server setup

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

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/9adrN1Dio8crTRSSE/builds/Ffes5tPnIauSQgrwE/openapi.json
