# Outdated Software Finder - EOL PHP, WordPress, Any Stack (`that_red_bird/outdated-software-finder`) Actor

Find end-of-life and vulnerable software in your stack. Give a component list (php 7.4, wordpress 5.8, ...) or the output of tech-stack-detector; get EOL status, days left and known-vulnerability counts from endoflife.date and OSV. Lead lists for agencies and MSPs.

- **URL**: https://apify.com/that_red_bird/outdated-software-finder.md
- **Developed by:** [mohamed alaya](https://apify.com/that_red_bird) (community)
- **Categories:** Developer tools, Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 site checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Outdated Software Finder - EOL PHP, WordPress, Any Stack

Give it a list of components ("php 7.4", "WordPress 5.8", "nodejs 16") or the output of the tech-stack-detector Actor, and it tells you which ones are end-of-life, how many days are left, what to upgrade to and how many known vulnerabilities the library versions have. For web agencies hunting upgrade leads, MSPs and IT asset teams.

Data comes from endoflife.date (about 480 products) and the OSV vulnerability database. No API keys.

### Input examples

```json
{ "components": ["php 7.4", "wordpress 5.8", "nodejs 16", "ubuntu 18.04"] }
```

```json
{ "components": ["npm:lodash 4.17.20", "jquery 1.12.4", "django 2.2"], "checkVulnerabilities": true }
```

```json
{ "techStackDatasetId": "<dataset id of a tech-stack-detector run>", "eolSoonDays": 365 }
```

### Input guide

| Field | What it does |
|---|---|
| `components` | One per line, name plus version: `php 7.4`, `WordPress 5.8.1`, `nodejs@16`. `npm:name version` forces a vulnerability lookup. |
| `techStackDatasetId` | Pick a tech-stack-detector dataset; each site's versioned technologies are checked and a per-site summary is added. |
| `includeUnknownVersions` | For datasets: also list known products whose version was not detected. |
| `checkVulnerabilities` | Count OSV advisories for library components (default on). |
| `eolSoonDays` | Support ending within this many days is flagged `eol-soon` (default 180). |
| `maxSites` | Cap on dataset rows processed. |

### Output

| Field | Meaning |
|---|---|
| `type` | `component`, `site-summary` or `error` |
| `site`, `source` | Domain (dataset input) or null (typed list) |
| `component`, `version`, `product`, `cycle` | What was checked and the matched release line |
| `status` | `eol`, `eol-soon`, `supported`, `version-unknown`, `unknown-product` |
| `eolDate`, `daysLeft` | End of support date and days remaining (negative = days since EOL) |
| `upgradeTo`, `newestSupported` | Newest maintained release line and its latest version |
| `vulnCount`, `highestSeverity`, `vulnIds` | OSV advisories for that exact version, highest severity seen |
| site summary | `eolCount`, `eolSoonCount`, `vulnerableCount`, `outdated`, `eolComponents` |

Sample row:

```json
{"type":"component","component":"php","version":"7.4","product":"php","cycle":"7.4","status":"eol","eolDate":"2022-11-28","daysLeft":-1407,"upgradeTo":"8.5","vulnCount":null}
```

### Use it with

- `tech-stack-detector` -> this Actor: detect the stack of a list of sites, then keep the sites whose summary says `outdated: true` as upgrade leads.
- Google Maps scraper -> `tech-stack-detector` -> this Actor for local-business prospecting.

### FAQ

**Why is vulnCount empty for PHP or nginx?** OSV tracks packages in library ecosystems (npm, PyPI, Packagist, Maven, RubyGems), not servers and runtimes. Those components get an end-of-life check only. Use the `npm:`-style prefix to force a package lookup.

**Why are many detected technologies skipped?** Most sites hide versions. Technologies without a detected version cannot be placed on a release line, so they are skipped unless you turn on `includeUnknownVersions`.

### Limits (honest)

- Version matching is by release line (7.4.33 matches the 7.4 line). A version that does not match any line is `version-unknown`.
- Vulnerability severity is read from the first 12 advisories only when there are more.
- Security patches that vendors backport (Debian, RHEL) are not visible; EOL dates are the upstream project's.
- Reading a tech-stack-detector dataset needs the Actor's full-permissions mode (it reads a storage you pick).

### Price

Pay per event: `site-checked` $0.003 per site with at least one checked component; a typed component list counts one event per 10 components. Example: 200 sites from tech-stack-detector cost $0.60 (sites with nothing checkable are free).

# Actor input Schema

## `components` (type: `array`):

Software to check, one per line: 'php 7.4', 'WordPress 5.8.1', 'nodejs@16', 'ubuntu 18.04'. About 480 products from endoflife.date are recognised. For library vulnerability counts you can force an ecosystem: 'npm:lodash 4.17.20'. Leave the sample to try the Actor.

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

Pick the output dataset of the tech-stack-detector Actor. Every site's detected technologies that have a version are checked for end-of-life status; a summary row per site is added. When a dataset is picked, the built-in sample list is not used.

## `checkVulnerabilities` (type: `boolean`):

Look up known vulnerabilities for library components (npm, PyPI, Packagist, Maven, RubyGems) in the OSV database. Servers and runtimes such as PHP, nginx or WordPress core are not covered by OSV and only get an end-of-life check.

## `eolSoonDays` (type: `integer`):

A component whose support ends within this many days is reported as eol-soon instead of supported.

## `maxSites` (type: `integer`):

Upper bound on how many tech-stack-detector rows (sites) are processed in one run.

## `includeUnknownVersions` (type: `boolean`):

For tech-stack-detector datasets: also output technologies that endoflife.date knows but whose version was not detected (status version-unknown, with the newest supported release). Off by default because most sites hide their versions.

## Actor input object example

```json
{
  "components": [
    "php 7.4",
    "wordpress 5.8",
    "nodejs 16",
    "python 3.8",
    "ubuntu 18.04",
    "jquery 1.12.4",
    "php 8.4",
    "laravel 11"
  ],
  "checkVulnerabilities": true,
  "eolSoonDays": 180,
  "maxSites": 500,
  "includeUnknownVersions": false
}
```

# Actor output Schema

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

No description

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

No description

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

No description

## `count` (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 = {
    "components": [
        "php 7.4",
        "wordpress 5.8",
        "nodejs 16",
        "python 3.8",
        "ubuntu 18.04",
        "jquery 1.12.4",
        "php 8.4",
        "laravel 11"
    ],
    "checkVulnerabilities": true,
    "eolSoonDays": 180,
    "maxSites": 500,
    "includeUnknownVersions": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("that_red_bird/outdated-software-finder").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 = {
    "components": [
        "php 7.4",
        "wordpress 5.8",
        "nodejs 16",
        "python 3.8",
        "ubuntu 18.04",
        "jquery 1.12.4",
        "php 8.4",
        "laravel 11",
    ],
    "checkVulnerabilities": True,
    "eolSoonDays": 180,
    "maxSites": 500,
    "includeUnknownVersions": False,
}

# Run the Actor and wait for it to finish
run = client.actor("that_red_bird/outdated-software-finder").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 '{
  "components": [
    "php 7.4",
    "wordpress 5.8",
    "nodejs 16",
    "python 3.8",
    "ubuntu 18.04",
    "jquery 1.12.4",
    "php 8.4",
    "laravel 11"
  ],
  "checkVulnerabilities": true,
  "eolSoonDays": 180,
  "maxSites": 500,
  "includeUnknownVersions": false
}' |
apify call that_red_bird/outdated-software-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,that_red_bird/outdated-software-finder"
        }
    }
}
```

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/eZNTWBzLCHyv3XoMM/builds/cNfE9xvNGfOdPylmj/openapi.json
