# Zenn Developer Feed Monitor - Creators & Topics (`maydit/zenn-developer-feed-monitor`) Actor

Monitor Zenn community RSS by creator, topic or trending selection. Export public article and book announcements, excerpts, literal mentions and saved changes. No article or chapter crawling.

- **URL**: https://apify.com/maydit/zenn-developer-feed-monitor.md
- **Developed by:** [Brandt May](https://apify.com/maydit) (community)
- **Categories:** Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 developer article observations

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

![Watch developer publishing activity — illustrative workflow](https://api.apify.com/v2/key-value-stores/YGxD9JRpduom8Q5Zd/records/zenn-developer-feed-monitor-345392d6254f.png?signature=nE1NJwqgD818R3MiXWoS)

[Open this Actor in Console](https://console.apify.com/actors/61EMAQVOYLvfPYTdV/input) · [Try a small run](#try-a-small-run) · [Cost](#cost)

**Mayd-It · Developer communities**

Follow publishing activity in Japan’s Zenn developer community. Use creator, topic or trending feeds to collect public article and book announcements for developer relations and product-mention workflows.

**Source scope:** Publisher titles, excerpts and links from public RSS. No login, API key or proxy; articles, paid books, chapters and comment threads are not crawled.

### What you get

- Public article and book announcements with canonical source identities.
- Creator, topic and publisher-selected trending feeds in one dataset.
- Literal mention evidence and saved headline or excerpt changes.

### Try a small run

Copy this exact input into the Actor’s JSON input editor, then run it.

```json
{
  "topics": [
    "typescript"
  ],
  "maxItemsPerFeed": 10,
  "maxResults": 10
}
```

This example selects up to ten entries from the TypeScript topic feed. `{}` instead uses up to ten current trending entries. Set `creators` or `topics` for your own watchlist; `includeTrending: true` adds trending alongside them. If both lists are empty, trending remains the fallback. Review the dataset and `SUMMARY` after the run.

### Understand your run

Open **Run report** in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use **CSV export** to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.

The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.

### Cost

**FREE / BRONZE: $0.002 per saved observation ($2 per 1,000).** SILVER: $1.60 per 1,000. GOLD / PLATINUM / DIAMOND: $1.20 per 1,000.

The Actor Start event is **$0.00005 per charged start unit**, with one unit per GB of Actor memory and a minimum of one. The Pricing tab shows the rate for your Apify tier. New, changed and ordinarily saved unchanged observations use the same result rate. Skipped unchanged rows, rejected events, duplicates and error diagnostics are not paid result rows. Use `onlyChanges` for repeated monitoring after establishing history.

### A real result

Selected fields from a recorded run on **10 October 2026**. This is an example of the output shape; source content and counters can change.

```json
{
  "postId": "kazurayam/articles/b2cc6af3cc7f25",
  "entryType": "article",
  "title": "ministaのMarkdownサポートを活用して \"お知らせ\" ページを実装してみた",
  "sourceHandle": "kazurayam",
  "publishedAt": "2026-10-10T12:48:34.000Z",
  "feedUrls": [
    "https://zenn.dev/topics/typescript/feed"
  ],
  "comparisonStatus": "not_requested"
}
```

The full row includes the publisher’s excerpt. `sourceHandle` is the URL namespace and can identify a publication rather than an individual author.

### More examples

#### Watch official Zenn creator updates

Read the official Zenn creator feed instead of a topic selection.

```json
{
  "creators": [
    "zenn"
  ],
  "maxItemsPerFeed": 10,
  "maxResults": 10
}
```

#### Compare saved TypeScript feed observations

Establish history for the TypeScript feed. Repeat sequentially with `onlyChanges: true` to save only new or changed observations.

```json
{
  "topics": [
    "typescript"
  ],
  "maxItemsPerFeed": 10,
  "maxResults": 100,
  "comparePrevious": true,
  "snapshotName": "example-typescript"
}
```

***

### Input reference

| Field | Meaning |
|---|---|
| creators | Up to 20 exact lowercase Zenn handles; URLs are not accepted. |
| topics | Lowercase ASCII Zenn topic slugs, such as `typescript` or `python`. At most 20 creator and topic feeds combined. |
| includeTrending | Add the publisher-selected trending feed; default false with an empty-source fallback. |
| maxItemsPerFeed | First entries in each feed’s supplied order, before keywords or comparison; default 10, maximum 20. |
| keywords | Up to 20 literal case-insensitive substrings. Any matching title or returned excerpt qualifies. |
| maxResults | Confirmed saved observations; default 20, maximum 500. Skipped unchanged rows do not consume this cap. |
| comparePrevious | Compare against saved observations; default false. |
| onlyChanges | Implies comparison and skips unchanged observations; default false. |
| snapshotName | Named history namespace, 1–40 letters, digits, underscores or hyphens. |
| maxRunSeconds | Default 240, minimum 30, maximum 3600; also bounded by the platform deadline minus 25 seconds. |

### Output reference

Each real observation includes `postId`, `entryType` (`article` or `book`), `title`, `excerpt`, `excerptTruncated`, `sourceHandle`, `creatorName`, `publishedAt`, `sourceUrl`, `feedUrls`, `matchedKeywords` and `observedAt`. The post ID is `URL-owner/articles-or-books/slug`. `sourceHandle` is the canonical URL namespace: it can name a publication rather than the individual author. `creatorName` is the feed's supplied creator display name; no author handle is inferred. Display names can be empty if omitted by the feed. A `thumbnailUrl` is included only when the feed supplies a usable HTTPS image URL; the image itself is never fetched.

Descriptions are the publisher’s plain-text excerpts. Excerpts are capped at 4,000 characters and `excerptTruncated` reports that cap. The Actor does not generate summaries, translate text, infer sentiment or fetch full article content. Keyword matching uses only the returned title and excerpt.

Comparison output is `comparisonStatus` (`not_requested`, `new`, `changed` or `unchanged`), `changedFields`, `previous` and `previousObservedAt`. Watched fields are title, excerpt, truncation flag, publisher date, canonical source namespace (`sourceHandle`) and creator display name. Thumbnail URLs, feed membership, matched keywords and observation time are excluded from comparison.

### Saved history and repeat runs

The first comparison run emits initial observations as `new`. Repeat the same bounded source window and `snapshotName` with `onlyChanges: true` to export only new or changed observations. An unchanged repeat legitimately saves zero rows. History records the last saved observation, so unchanged skipped runs do not advance `previousObservedAt`.

Named stores use `maydit-zenn-feed-<snapshotName>`. History is keyed by post identity within that namespace. Only confirmed saved rows update it. A rejected spending-limit write, filtered entry or unsaved result cannot be marked seen. Existing records are retained when an entry disappears from the recent window; no deletion is inferred.

Run a snapshot namespace sequentially. A reread catches some overlapping writes, but it is not an atomic lock. Use different names for independent workflows. Invalid saved history is reported as an error and preserved; select a new name to start again.

### Coverage and limitations

Zenn’s documented feeds expose recent publisher-selected windows, including article and book announcements. The trending feed is a selection, not a complete chronology or a measurement of popularity. Books receive the same public feed metadata treatment; no chapters or paid book content are opened. Scraps, full-history parameters and site search are not supported.

An edit is detected only while the post is visible in the selected feed window. A publication date is the source’s publication date, not an edit timestamp. This Actor does not expose engagement counts, follower counts, comments, ranking scores or historical backfill. Feeds can lag or change between requests.

Overlapping feeds are deduplicated by post identity and their `feedUrls` are retained. If the same post has conflicting fields in two responses, the first observation is retained and the conflict is recorded in SUMMARY. Treat that run as partial.

SUMMARY records actual saved and observed counts, per-feed available/selected entries, filter and unchanged skips, failed sources, sources not reached and deadline or spending stops. A selected result/window cap is scope, not an operational failure. Partial runs can contain useful paid observations. All-source failures with no usable output fail rather than producing fake error rows.

Requests respect robots.txt, validate public network destinations, reject redirects and bound response size and retry delays. Robots restrictions or upstream errors are reported. There is no fallback through private APIs or alternate anti-bot routes.

### Source and reuse

The platform documents its feeds here: [official RSS instructions](https://zenn.dev/zenn/articles/zenn-feed-rss). This Actor is independent of the platform. Public syndication does not transfer copyright; retain the publisher link and respect the source’s terms when reusing excerpts.

### Development

Node 20.19 or newer; exact `apify` 3.7.2 and `cheerio` 1.1.2, with `basic-ftp` overridden to 6.2.2. Run `npm ci --ignore-scripts --omit=optional`, then `npm test` or `npm start`. Use isolated `CRAWLEE_STORAGE_DIR` directories for local runs. The Docker image uses Node 20. No downloaded code or post content is executed.

### Troubleshooting and support

| If you see… | Check this |
| --- | --- |
| A keyword has no matches | Matching checks only returned titles and excerpts within the selected feed window. It is not a site-wide search or semantic classifier. |
| A publication appears as the source handle | That field comes from the canonical URL namespace. Use the source-supplied `creatorName` separately; an author handle is not inferred. |
| Trending does not look chronological | Trending is the publisher’s selection, not a full chronology or a measured popularity score. |

For help, open an Actor issue or contact **bmay@mayd-it.com**. Include the run ID, selected sources and the relevant `SUMMARY` message. Do not send credentials. This Actor is independent of the platform.

# Actor input Schema

## `creators` (type: `array`):

Up to 20 exact Zenn creator handles, for example zenn. No profile URLs. When creators and topics are empty, the current trending feed is the code fallback.

## `topics` (type: `array`):

Up to 20 exact ASCII Zenn topic slugs, such as typescript or python. Uses each documented recent topic RSS feed, not site search.

## `includeTrending` (type: `boolean`):

Include the publisher-selected trending RSS feed alongside explicit creators or topics. With no explicit source and this field false, trending is still the code fallback. Trending feed order is not chronological.

## `keywords` (type: `array`):

Up to 20 case-insensitive substrings. Match any keyword in the returned title or excerpt, including Japanese text. Applied after the per-feed window limit; no language translation or sentiment inference.

## `maxItemsPerFeed` (type: `integer`):

Select the first entries in publisher feed order before literal keyword filtering and comparison. This recent feed window is not a full archive.

## `maxResults` (type: `integer`):

Maximum confirmed saved posts. Duplicate feed entries and unchanged skipped rows do not consume this limit. Selected scope limits do not mean upstream failure.

## `comparePrevious` (type: `boolean`):

Compare title, excerpt, publisher date and creator identity to prior saved observations in a named store. Initial observations are new. Only confirmed saved rows advance history.

## `onlyChanges` (type: `boolean`):

Implies comparePrevious. The initial run emits new observations; unchanged repeats can correctly emit zero rows. Feed disappearance does not establish deletion.

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

1-40 letters, digits, underscores or hyphens. Use a separate namespace for each workflow and run the same namespace sequentially.

## `maxRunSeconds` (type: `integer`):

Own deadline, also bounded by the platform deadline minus 25 seconds. Requests, retries and history writes share this budget.

## Actor input object example

```json
{
  "creators": [],
  "topics": [],
  "includeTrending": false,
  "keywords": [],
  "maxItemsPerFeed": 10,
  "maxResults": 20,
  "comparePrevious": false,
  "onlyChanges": false,
  "snapshotName": "default",
  "maxRunSeconds": 240
}
```

# Actor output Schema

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

Public publisher titles and excerpts, canonical source links and optional saved comparisons.

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

Readable summary of saved records, reported source coverage, limits and next steps. Available when this run saves its SUMMARY.

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

Download saved dataset records as a CSV file for spreadsheets and other tools.

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

Actual saved rows, selected feed windows, skips, source errors and deadline or spending stops.

# 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 = {
    "creators": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("maydit/zenn-developer-feed-monitor").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 = { "creators": [] }

# Run the Actor and wait for it to finish
run = client.actor("maydit/zenn-developer-feed-monitor").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 '{
  "creators": []
}' |
apify call maydit/zenn-developer-feed-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maydit/zenn-developer-feed-monitor"
        }
    }
}
```

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/61EMAQVOYLvfPYTdV/builds/27Xccjxakb17vXYqW/openapi.json
