# NodeInfo Instance Extractor (`datamule/nodeinfo-instance-extractor`) Actor

Point at ANY fediverse instance (Mastodon, Lemmy, Misskey, Pixelfed, PeerTube…) and extract its NodeInfo: software name & version, protocols, services, open-registrations, user counts, local posts & comments, plus the raw NodeInfo JSON. One generic runner for every fediverse server.

- **URL**: https://apify.com/datamule/nodeinfo-instance-extractor.md
- **Developed by:** [Datamule](https://apify.com/datamule) (community)
- **Categories:** Developer tools, Social media
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 instance parseds

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?

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

## NodeInfo Instance Extractor

Turn a list of NodeInfo-speaking fediverse hosts into one comparable dataset row per reachable host for researchers, community operators, and monitoring workflows.

### Try it now

Use one stable public host for a bounded first run:

```json
{"instances":["mastodon.social"]}
```

### Example output

This row was captured from that exact input in a local run at `2026-07-20T15:13:10Z`. The run succeeded and returned one genuine dataset row. Selected fields are shown below; `_raw` and several null optional fields are omitted for readability. Software versions and usage counts are advertised by the server and can change.

```json
{
  "host": "mastodon.social",
  "_source": "mastodon.social",
  "nodeinfo_version": "2.0",
  "schema_rel": "http://nodeinfo.diaspora.software/ns/schema/2.0",
  "software_name": "mastodon",
  "software_version": "4.6.3",
  "protocols": ["activitypub"],
  "open_registrations": true,
  "total_users": 3344371,
  "active_month": 267542,
  "active_halfyear": 683735,
  "local_posts": 181870144,
  "local_comments": null,
  "node_name": "Mastodon"
}
```

### Pricing

The Actor uses pay per event pricing. It charges one `record` event for each returned instance row.

- FREE-tier price: `$0.0005` per `record`.
- One-host trial ceiling: `1 row x $0.0005 = $0.0005` in PPE event charges.
- Apify infrastructure usage is separate and is not included in that ceiling.
- A skipped host emits no row and adds no `record` charge.

### Inputs, defaults, limits, and scaling

| Field | Required | Default or prefill | Behavior |
|---|---:|---|---|
| `instances` | Yes | The Store form is prefilled with `mastodon.social`, `lemmy.world`, and `misskey.io`. | Accepts bare hostnames or base URLs. The Actor normalizes and deduplicates them, then queries each unique host. |
| `userAgent` | No | `apify-nodeinfo-instance-extractor (+https://apify.com/datamule)` | Replaces the default User-Agent when a server rejects it. |
| `extraHeaders` | No | No extra headers | Adds request headers for deployments that require them. See the safety note under Troubleshooting. |

The one-host payload above is cheaper than the three-host Store prefill. If all three prefilled hosts return rows, its maximum PPE event charge is `$0.0015`, excluding Apify infrastructure usage.

Source-enforced behavior and limits:

- Input paths are stripped, hosts are lowercased, ports are preserved, and duplicate normalized hosts are processed once. The run fails if no valid host remains.
- There is no fixed source-level cap on the number of input hosts. Hosts are processed sequentially, so large lists and slow endpoints increase run time.
- Each host can emit at most one row. Cost scales with successful unique hosts, not attempted hosts.
- NodeInfo discovery starts at `https://<host>/.well-known/nodeinfo`, follows redirects, and then fetches the advertised document URL. Each request has a 45-second timeout. Transient network errors, HTTP 429, and HTTP 5xx responses receive up to three total attempts.
- Each discovery or NodeInfo response is limited to 8 MiB.
- `_raw` stores compact JSON up to 16,384 characters. A larger document is replaced with a valid `{"_truncated":true}` marker instead of partial JSON.

### Output fields

| Field | Meaning |
|---|---|
| `host` | Normalized host that was queried. |
| `_source` | Original input value associated with the normalized host. |
| `nodeinfo_version` | Version reported inside the selected NodeInfo document. |
| `schema_rel` | Schema relation selected from the discovery document. |
| `software_name` | Server software name, such as `mastodon`, when advertised. |
| `software_version` | Server software version when advertised. |
| `software_repository` | Software source repository URL when advertised. |
| `software_homepage` | Software homepage URL when advertised. |
| `protocols` | Protocol names advertised by the server. |
| `services_inbound` | Advertised inbound services. |
| `services_outbound` | Advertised outbound services. |
| `open_registrations` | Whether the server reports that registrations are open. |
| `total_users` | Server-reported total user count. |
| `active_month` | Server-reported active users for the monthly window. |
| `active_halfyear` | Server-reported active users for the half-year window. |
| `local_posts` | Server-reported local post count. |
| `local_comments` | Server-reported local comment count. |
| `node_name` | Free-form node name from NodeInfo metadata. |
| `node_description` | Free-form node description from NodeInfo metadata. |
| `_raw` | Compact original NodeInfo JSON, or a truncation marker when it exceeds the stored size limit. |

Server-advertised fields can be absent from a NodeInfo document and therefore appear as `null`.

### Practical use cases

- Compare the software, versions, registration policy, and activity reported by a chosen set of instances.
- Build a point-in-time inventory for community operations or fediverse research.
- Run the same watchlist on a schedule and store the resulting datasets to observe changes over time.
- Check self-reported protocol and activity details before migration or federation planning.

### Coverage, freshness, and limitations

For each host, the Actor requests `/.well-known/nodeinfo`, selects the highest recognizable numeric schema version (for example, `2.1` over `2.0` or `1.x`), and fetches the advertised document. It works only when the host exposes a usable NodeInfo discovery link and JSON document.

Results are point-in-time values advertised by the server. The Actor does not independently verify the counts, retain history, or guarantee that a server's document is complete or current. Optional fields vary by software and may be absent or `null`.

An unreachable host, non-NodeInfo host, unusable discovery link, or non-JSON response is skipped with a warning while other hosts continue. If every host fails, the run fails instead of returning an empty successful dataset. This is not an exhaustive fediverse directory and carries no historical or completeness guarantee.

Query only hosts you are authorized to access and follow their operating policies.

### Troubleshooting

| Symptom | What to check |
|---|---|
| Missing, empty, or malformed input | Pass a non-empty `instances` array containing bare hostnames or base URLs. At least one value must normalize to a valid host. |
| HTTP 403 with the default User-Agent | Set `userAgent` to a descriptive value accepted by that server. Some deployments reject generic or unfamiliar user agents. |
| `no usable NodeInfo links[]` warning | Open `https://<host>/.well-known/nodeinfo` and confirm it returns JSON with a NodeInfo `links` entry containing an `href`. |
| `did not return JSON` warning | The endpoint returned HTML, text, or another non-JSON body. Confirm the host supports NodeInfo and that its advertised document URL is working. |
| Some hosts are missing from the dataset | Read the run warnings. Failed hosts are skipped, and duplicate inputs that normalize to the same host produce at most one row. |
| All-host failure | Test one host at a time, correct typos, and verify both NodeInfo endpoints. A batch with zero successful hosts fails honestly. |
| Extra headers are required | `extraHeaders` are sent on both the discovery request and the advertised NodeInfo document request. Use them only when you trust both URLs. Header values are not logged by the Actor, but run inputs may be retained by Apify, so never place reusable credentials in public examples or shared tasks. |

# Actor input Schema

## `instances` (type: `array`):

One or more fediverse instances to census — as bare hostnames OR base URLs. Each is normalized to its host and queried at /.well-known/nodeinfo (the NodeInfo discovery protocol every fediverse server implements). Works against ANY NodeInfo-speaking software: Mastodon, Lemmy, Misskey, Pixelfed, PeerTube, Friendica, GoToSocial, Pleroma/Akkoma, Bookwyrm, WriteFreely and more. Examples: mastodon.social, https://lemmy.world, misskey.io, https://pixelfed.social/.

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

Optional custom User-Agent header. Some instances 403 a default UA; a descriptive browser-ish or bot UA usually works. Leave empty to use the actor's default descriptive UA.

## `extraHeaders` (type: `object`):

Optional extra HTTP headers as a JSON object, e.g. {"x-api-key": "..."} for gated / rate-limited deployments. Not required for public instances — anonymous read is the point of NodeInfo. Header values are never logged.

## Actor input object example

```json
{
  "instances": [
    "mastodon.social",
    "lemmy.world",
    "misskey.io"
  ]
}
```

# Actor output Schema

## `results` (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 = {
    "instances": [
        "mastodon.social",
        "lemmy.world",
        "misskey.io"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamule/nodeinfo-instance-extractor").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 = { "instances": [
        "mastodon.social",
        "lemmy.world",
        "misskey.io",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("datamule/nodeinfo-instance-extractor").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 '{
  "instances": [
    "mastodon.social",
    "lemmy.world",
    "misskey.io"
  ]
}' |
apify call datamule/nodeinfo-instance-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datamule/nodeinfo-instance-extractor"
        }
    }
}

```

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/AEH6c1O5LjBUdhSjL/builds/kUpLaf2Dpmx67CqhX/openapi.json
