# Wattpad Scraper - Stories, Chapters, Authors & Comments (`abotapi/wattpad-scraper`) Actor

Scrape Wattpad stories by keyword, tag, category, language or URL. Extract authors, reads, votes, tags, completion status and chapter lists, with optional chapter text, full comment threads, inline paragraph comments and replies.

- **URL**: https://apify.com/abotapi/wattpad-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.30 / 1,000 results

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

## Wattpad Story, Chapter and Comment Scraper

Pull structured records out of Wattpad, the social storytelling platform. Search the site's own story index by keyword, category, language and completion state, or paste story and chapter links you already have. Every story comes back with its author, blurb, cover, tags, categories, language, read, vote and comment counters, and its full chapter list. Switch on the extras and each story also brings the body text of every chapter, split into the site's own numbered paragraphs, and the whole comment thread: end-of-chapter comments and inline comments written against one specific paragraph, each one matched back to the paragraph it belongs to.

Everything here comes from what Wattpad shows any anonymous visitor. There is no login, no account, no sign up and no credential of any kind anywhere in this actor.

### Why This Scraper?

- **Inline paragraph comments, matched to their paragraph.** Wattpad's most distinctive data is the comment a reader leaves on one line of one chapter. This actor returns those, each carrying the id of the paragraph it was written on, so a comment can be placed next to the sentence that caused it. Comments left at the end of a chapter come back in the same pass and are labelled separately.
- **One row per story, chapters and comments nested inside.** A run that reads ten stories and forty thousand comments exports ten rows, so the dataset stays joinable and you are billed for stories, not for comments.
- **The chapter list costs nothing.** Every chapter's id, title, link, length, publish stamp and its own read, vote and comment counters arrive inside the story record. Only the chapter body text and the comment thread need extra requests, and a story that takes them is billed one `detail-enrichment` event once, however many chapters or comment pages it needed.
- **Honest filters.** The site's index accepts a tag parameter and a maturity parameter and then ignores both, which is easy to mistake for a working filter. This actor applies those two itself, over the data the site returns, and says so in the input rather than handing back an unfiltered set that looks filtered.
- **Real end-of-feed detection.** The comment feed signals "no more pages" by dropping a key, not by returning an empty list, and a missing comment list means a refused request rather than a quiet thread. Those two cases are told apart, so a blocked request never masquerades as a story with no comments.
- **"No results" is checked before it is reported.** A search that returns nothing on its first page looks exactly like a search the site briefly declined to answer: same status, same empty body. Before a run reports an empty result set, it spends one small check read that the site always answers. If that check comes back with results, your search really is empty and the run succeeds quietly. If it does not, the run reports a connection problem instead of handing you a successful run with zero rows.
- **Recurring monitoring built in.** Incremental mode returns only what changed since the last run of the same search, and resume continues one interrupted pull without paying for rows you already have.

### Data You Get

> Sample shape, values are illustrative placeholders, not from a live story.

| Field | Example |
|---|---|
| `storyId` | `"100000001"` |
| `title` | `"The Sample Werewolf Chronicles"` |
| `url` | `"https://www.wattpad.com/story/100000001-the-sample-werewolf-chronicles"` |
| `description` | `"A one paragraph blurb, exactly as the author wrote it."` |
| `coverUrl` | `"https://img.example-cdn.test/cover/100000001-256.jpg"` |
| `author` | `"sample_author"` |
| `authorUrl` | `"https://www.wattpad.com/user/sample_author"` |
| `language` | `"English"` |
| `categories` | `["Werewolf"]` |
| `tags` | `["werewolf", "alpha", "mates"]` |
| `isCompleted` | `true` |
| `isMature` | `false` |
| `numParts` | `44` |
| `readCount` | `1234567` |
| `voteCount` | `89012` |
| `commentCount` | `34567` |
| `wordCount` | `412345` |
| `chapters` | `[{"chapterId": "200000001", "title": "Chapter 1", "commentCount": 876}]` |
| `chaptersReturned` | `44` |
| `comments` | `[{"scope": "inline", "paragraphId": "5a1b2c3d", "text": "This line broke me."}]` |
| `commentsReturned` | `50` |
| `commentsComplete` | `false` |
| `scanComplete` | `true` |
| `changeType` | `"NEW"` |

#### Comments, and what a comment row carries

Wattpad publishes two kinds of comment and this actor returns both from a single walk of each chapter:

- **Inline comments** are written against one paragraph. Their `scope` is `"inline"` and they carry a `paragraphId` that matches the `id` of an entry in that chapter's `paragraphs` list, so with chapter text switched on you can put the comment next to the exact sentence it answers.
- **End-of-chapter comments** sit under the chapter as a whole. Their `scope` is `"part"` and their `paragraphId` is `null`.

Every comment row carries the commenter's public display handle and profile address, the body text, the created and modified stamps, the site's own status value, its reply count and its permalink. `replies` is filled only when `includeReplies` is on. One thing is deliberately left out: the commenter's avatar image. A reader's photograph adds nothing to what they wrote, and republishing it at scale is a different product from publishing the comment. The same applies to the author's avatar on the story row.

`commentCount` on the story is the total the site itself declares and is usually far larger than `commentsReturned`. `commentsComplete` tells you whether the thread was read to its end or stopped at `maxCommentsPerStory`. Raise the cap to walk further.

#### Known limits of the public index

These are the site's own behaviours, measured rather than assumed. None of them is a reason to log in, and this actor never does.

- **Mature-flagged stories are not returned by the public search index.** Anonymous search results come back with the mature flag false across the board, including on queries that plainly should surface mature work. Use URL mode for a mature story you already know: fetching a story by its own link or id works regardless of its flag.
- **The advertised result total is not a stop condition, and search stops at result 10,000.** A keyword search can advertise hundreds of thousands of matches and still stop serving rows a little past result 10,000. Category listings and the default listing advertise a flat 1,500. The run bounds on an empty page instead of the advertised total, reports any scope that was cut short, and refuses to expire anything from an incomplete scan.
- **Search pages are not perfectly stable.** Two neighbouring pages of the same search can overlap. Stories are deduplicated by id across the whole walk.
- **The index ignores its own tag and maturity parameters.** A tag that does not exist returns exactly the same rows as a real one, which is why `tags` and `mature` are applied by this actor after each story is read. A run with either set reads more stories than it returns, and `maxItems` counts what is returned.
- **Requesting an unsupported field returns the record without it, and without an error.** The actor only asks for fields the site documents on each surface, so a missing value always means the site had no value, never that the request was malformed.

### How to Use

Search the index, chapter list included, no extra requests per story:

```json
{
  "mode": "search",
  "query": "werewolf",
  "filter": "complete",
  "maxItems": 100
}
```

A category in one language, with the comment thread:

```json
{
  "mode": "search",
  "category": "Horror",
  "language": "Spanish",
  "fetchComments": true,
  "commentScope": "inline",
  "maxCommentsPerStory": 200,
  "maxItems": 25
}
```

Pasted links, with the full chapter text and the replies under each comment:

```json
{
  "mode": "url",
  "startUrls": [
    "https://www.wattpad.com/story/12702726-werewolf-committee"
  ],
  "fetchChapterText": true,
  "fetchComments": true,
  "includeReplies": true,
  "maxRepliesPerComment": 10
}
```

Daily monitoring of one search, returning only what changed:

```json
{
  "mode": "search",
  "query": "enemies to lovers",
  "tags": ["slowburn"],
  "incrementalMode": true,
  "stateKey": "slowburn-watch",
  "maxItems": 0
}
```

### Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `search` | `search` to walk the story index, `url` to scrape pasted links. |
| `query` | string | `werewolf` (prefill) | **Search mode only.** Free text keyword. Empty returns the site's default listing. |
| `category` | select | `any` | **Search mode only.** One of the site's own 22 categories. Checked live every run. |
| `filter` | select | `all` | **Search mode only.** Every story, or finished stories only. Applied by the site. |
| `language` | select | `any` | **Search mode only.** One of the 26 languages the site says stories are written in. Resolved live to the site's own numeric language id and sent with the search, so the site narrows the results. |
| `startUrls` | array | one sample story link | **URL mode only.** Story links, chapter links or bare numeric story ids, mixed freely. |
| `tags` | array | (none) | **Both modes.** Keep only stories carrying at least one of these tags. Applied by the actor, not the site. |
| `mature` | boolean | `true` | **Both modes.** Leave on to keep every story, switch off to drop mature-flagged ones. |
| `fetchChapters` | boolean | `true` | Include the chapter list. Free: it ships inside the story record. |
| `fetchChapterText` | boolean | `false` | Also download every chapter's body text. One extra request per chapter. |
| `fetchComments` | boolean | `false` | Also download the comment thread, end-of-chapter and inline together. |
| `commentScope` | select | `all` | Keep both kinds of comment, end-of-chapter only, or inline only. |
| `maxCommentsPerStory` | integer | `50` | Cap on comments per story across all its chapters. `0` returns the story without its thread. |
| `includeReplies` | boolean | `false` | Also fetch the replies under each comment. One extra request per comment that has any. |
| `maxRepliesPerComment` | integer | `5` | Cap on replies per comment. `0` for every reply published. |
| `maxItems` | integer | `100` | The run's cap, counted on stories RETURNED. `0` for unlimited. |
| `maxPages` | integer | `0` | Index pages per search scope. `0` means no limit. |
| `resumeFromRunId` | string | (none) | Continue one interrupted run from its run or dataset id. |
| `incrementalMode` | boolean | `false` | Return only what changed since the last run of the same search. |
| `stateKey` | string | (none) | Name a monitoring campaign, or deliberately share state. |
| `emitUnchanged` | boolean | `false` | Also return unchanged rows. These are billed. |
| `emitExpired` | boolean | `false` | Also return rows that disappeared. These are billed. |
| `proxy` | object | Apify Proxy | Connection configuration. The standard pool is enough for this site. |
| `mcpConnectors` | array | (none) | Optional MCP connectors to pipe results into. |
| `notionParentPageUrl` | string | (none) | Notion parent page id, for the Notion connector. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

#### Incremental mode, and what counts as a change

In incremental mode each story carries `changeType` (`NEW`, `UPDATED`, `REAPPEARED` or `EXPIRED`), `changedFields`, `firstSeenAt` and `lastSeenAt`.

What counts as a change here is an EDIT, not engagement drift. The engagement counters `readCount`, `voteCount` and `commentCount` are deliberately left out of the comparison, and so are the two nested arrays `chapters` and `comments`: on a live story those move between two reads minutes apart, so including them would mark every story UPDATED on every run and the change feed would be worthless. A story whose read count doubled overnight is therefore reported UNCHANGED, on purpose.

What IS compared: `numParts`, `title`, `description`, `tags`, `categories`, `isCompleted`, `isMature`, `language`, `coverUrl` and the site's own `modifiedAt`. So a new chapter, a retitle, a rewritten blurb, a tag or category edit and a completion flip all still classify as UPDATED and still name the exact field in `changedFields`. `comments`, `chapters`, `readCount`, `voteCount` and `commentCount` never appear there.

`EXPIRED` rows are only produced once a run has fully scanned the tracked search, so never after a capped run, never after a resumed run, and never when a scope hit the site's own result-depth limit. A chapter-text or comment request that failed does not enter the baseline as a real change either: the previous run's values are carried forward instead, so a one-off connection problem cannot fake an update.

### Send results into your apps (MCP connectors)

Results can optionally be piped into the apps you already use, through Model Context Protocol connectors, without changing the dataset at all.

1. Authorize a connector under Apify, Settings, API & Integrations.
2. Select it in the **Export to your apps (MCP connectors, optional)** section of the input (`mcpConnectors`).
3. For Notion, set `notionParentPageUrl` to the page under which item pages should be created.
4. `maxNotifyListings` caps how many items are written to each connector per run.

Supported out of the box: Notion, Linear, Airtable and Apify. What gets written is a condensed, human readable summary per item, a title plus the key fields flattened to plain text, not the full JSON: nested objects collapse to their main value and arrays trim to a few names. The complete record always stays in the Apify dataset. If a connector fails, the run still succeeds and the dataset is unaffected.

### Output Example

> Sample shape, values are illustrative placeholders, not from a live story.

```json
{
  "storyId": "100000001",
  "title": "The Sample Werewolf Chronicles",
  "url": "https://www.wattpad.com/story/100000001-the-sample-werewolf-chronicles",
  "description": "A one paragraph blurb, exactly as the author wrote it.",
  "coverUrl": "https://img.example-cdn.test/cover/100000001-256.jpg",
  "author": "sample_author",
  "authorUrl": "https://www.wattpad.com/user/sample_author",
  "language": "English",
  "categories": ["Werewolf"],
  "tags": ["werewolf", "alpha", "mates"],
  "isCompleted": true,
  "isMature": false,
  "rating": 1,
  "copyright": 1,
  "numParts": 44,
  "readCount": 1234567,
  "voteCount": 89012,
  "commentCount": 34567,
  "wordCount": 412345,
  "firstPartId": "200000001",
  "createdAt": "2026-01-01T00:00:00Z",
  "modifiedAt": "2026-01-02T00:00:00Z",
  "chapters": [
    {
      "chapterId": "200000001",
      "title": "Chapter 1: The Sample Beginning",
      "url": "https://www.wattpad.com/200000001-sample-chapter-one",
      "wordCount": 8123,
      "rating": 1,
      "isDraft": false,
      "createdAt": "2026-01-01T00:00:00Z",
      "modifiedAt": "2026-01-01T00:00:00Z",
      "readCount": 98765,
      "voteCount": 4321,
      "commentCount": 876,
      "photoUrl": "",
      "videoId": "",
      "text": "The chapter body appears here when chapter text is switched on.",
      "paragraphs": [
        { "id": "5a1b2c3d", "text": "The first paragraph of the chapter." }
      ]
    }
  ],
  "chaptersReturned": 1,
  "comments": [
    {
      "commentId": "200000001_5a1b2c3d_1767225600_aaaa1111",
      "scope": "inline",
      "paragraphId": "5a1b2c3d",
      "text": "This line broke me.",
      "author": "sample_reader_01",
      "authorUrl": "https://www.wattpad.com/user/sample_reader_01",
      "createdAt": "2026-01-01T00:00:00Z",
      "modifiedAt": "2026-01-01T00:00:00Z",
      "status": "active",
      "replyCount": 1,
      "url": "https://www.wattpad.com/200000001-sample-chapter-one",
      "replies": [
        {
          "commentId": "200000001_5a1b2c3d_1767225601_bbbb2222",
          "scope": "inline",
          "paragraphId": "5a1b2c3d",
          "text": "Same, I had to put the phone down.",
          "author": "sample_reader_02",
          "authorUrl": "https://www.wattpad.com/user/sample_reader_02",
          "createdAt": "2026-01-01T00:00:00Z",
          "modifiedAt": "2026-01-01T00:00:00Z",
          "status": "active",
          "replyCount": 0,
          "url": "https://www.wattpad.com/200000001-sample-chapter-one",
          "replies": []
        }
      ]
    },
    {
      "commentId": "200000001__1767225602_cccc3333",
      "scope": "part",
      "paragraphId": null,
      "text": "Updating soon, I hope.",
      "author": "sample_reader_03",
      "authorUrl": "https://www.wattpad.com/user/sample_reader_03",
      "createdAt": "2026-01-01T00:00:00Z",
      "modifiedAt": "2026-01-01T00:00:00Z",
      "status": "active",
      "replyCount": 0,
      "url": "https://www.wattpad.com/200000001-sample-chapter-one",
      "replies": []
    }
  ],
  "commentsReturned": 2,
  "commentsComplete": false,
  "scanComplete": true,
  "enrichmentSkipped": false,
  "scrapedAt": "2026-01-02T00:00:00Z",
  "sourceUrl": "https://www.wattpad.com/story/100000001-the-sample-werewolf-chronicles",
  "changeType": "NEW",
  "changedFields": [],
  "firstSeenAt": "2026-01-02T00:00:00Z",
  "lastSeenAt": "2026-01-02T00:00:00Z"
}
```

### Plan Requirement

Runs on any Apify account. Enable Apify Proxy in the Connection section for the most reliable results. No Wattpad account, login or subscription is needed, and none is used.

# Actor input Schema

## `mode` (type: `string`):

Choose 'search' to walk the site's story index by keyword, category, language and completion state, or 'url' to scrape pasted story links, chapter links and plain story ids.

## `query` (type: `string`):

Only used when mode = search, ignored in url mode. Free text, for example 'werewolf', 'enemies to lovers' or an author name. Leave empty to read the site's default listing instead of a keyword search. A keyword search reaches a much deeper result set than the category and default listings, which the site caps at 1,500 rows.

## `category` (type: `string`):

Only used when mode = search, ignored in url mode. One of the site's own categories. The list is checked against the site's OWN published category list on every run, so a category the site has renamed or retired is reported by name instead of being dropped silently. Note the site's own behaviour: a category listing is capped at 1,500 rows, far below a keyword search.

## `filter` (type: `string`):

Only used when mode = search, ignored in url mode. Keep every story, or keep only the ones the author has marked finished. Applied by the site itself: a completed-only keyword search returns a genuinely smaller result set, not the same set with rows dropped afterwards.

## `language` (type: `string`):

Only used when mode = search, ignored in url mode. The language a story is written in. Applied by the site itself: the name you pick is resolved to the site's own numeric language id against the list it publishes on the day of the run, and that id is sent with the search, so the site returns a smaller result set instead of this actor reading the whole index and dropping most of it. The 26 values offered are the languages the site says stories can be written in; the other languages it publishes exist for its own interface only. A value the site has since retired stops the run by name. Leave on 'Any language' to search every language.

## `startUrls` (type: `array`):

Only used when mode = url, ignored in search mode. Story addresses of the form /story/<id>-slug, chapter addresses of the form /<chapterId>-slug, or plain numeric story ids. Mix all three freely.

## `tags` (type: `array`):

Optional, applies in both modes. Tags written the way they appear under a story, for example 'werewolf', 'enemiestolovers' or 'shortstory'. Capitals and spacing do not matter. A story is kept when it carries at least one of them. Leave empty to keep every story. Because the site's own index ignores its tag parameter, this is applied to the tag list the site returns on every story, so no extra request is made and nothing is charged for it.

## `mature` (type: `boolean`):

On by default, applies in both modes. Leave on to keep every story. Switch off to drop stories the site flags as mature, judged on each story's own flag after it is read. Worth knowing before you rely on it: the site's public search index does not return mature-flagged stories at all, so this bites in url mode and on stories reached by their own link, and changes almost nothing in search mode.

## `fetchChapters` (type: `boolean`):

On by default and free of charge. Returns the story's chapter list: each chapter's id, title, link, publish and update stamps, length, and its own read, vote and comment counters. These arrive inside the story record, so this costs no extra request and never triggers a detail-enrichment charge on its own.

## `fetchChapterText` (type: `boolean`):

Off by default. Downloads the body text of every chapter returned, split into the site's own numbered paragraphs so an inline comment can be matched back to the paragraph it was written on. This is ONE EXTRA REQUEST PER CHAPTER, and a long story can carry over a hundred chapters, so switch it on deliberately. The story is billed a single detail-enrichment event however many chapters it took.

## `fetchComments` (type: `boolean`):

Off by default. Walks the story's comment thread chapter by chapter and returns every comment with its author, body, exact time, reply count and permalink. Both kinds come back in one pass: comments left at the end of a chapter, and inline comments written against one specific paragraph, each carrying the paragraph id it belongs to. Extra requests, billed as the same single detail-enrichment event per story.

## `commentScope` (type: `string`):

Used with the comment thread. The site returns end-of-chapter comments and inline paragraph comments in one walk, so all three settings cost the same requests; this decides what is kept in the record. Inline comments carry the paragraph they were written on, end-of-chapter comments do not.

## `maxCommentsPerStory` (type: `integer`):

Cap on how many comments are returned for one story, counted across all of its chapters. Use 0 to return the story without its thread. Popular stories carry hundreds of thousands of comments, so a cap keeps a run predictable. Each record reports how many were returned and whether the thread was exhausted.

## `includeReplies` (type: `boolean`):

Off by default. A comment's reply count always comes back; switch this on to also fetch the replies themselves, which is one extra request per comment that has any. Still billed inside the same single detail-enrichment event for that story.

## `maxRepliesPerComment` (type: `integer`):

Used only when replies are fetched. Cap on how many replies are returned under one comment. Use 0 for every reply the site publishes for it.

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

Maximum number of stories to return across the whole run. Use 0 for unlimited. Note the site's own limit underneath it: one search scope stops serving rows past result 10,000 even when it advertises a far larger total, and category and default listings stop at 1,500. When a scope is cut short that way the run says so, and incremental mode will not mark anything expired from a scan it knows was incomplete.

## `maxPages` (type: `integer`):

Maximum number of index pages read per search scope. 0 means no limit, which is the default: the run then stops only at Max results, at the end of the results, or at the site's own depth limit.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull without returning or charging for stories already collected there. Use this after an interrupted run. For recurring daily monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns every matching story as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED stories. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately for each mode, target and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the mode, targets and filters, so different searches never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return stories that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return stories that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, so never when Max results capped it, never when Resume was used, and never when a scope hit the site's own result-depth limit. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.

## `proxy` (type: `object`):

Apify Proxy is recommended. The standard pool is the default and is sufficient for this site.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "query": "werewolf",
  "category": "any",
  "filter": "all",
  "language": "any",
  "startUrls": [
    "https://www.wattpad.com/story/12702726-werewolf-committee"
  ],
  "mature": true,
  "fetchChapters": true,
  "fetchChapterText": false,
  "fetchComments": false,
  "commentScope": "all",
  "maxCommentsPerStory": 50,
  "includeReplies": false,
  "maxRepliesPerComment": 5,
  "maxItems": 10,
  "maxPages": 0,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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 = {
    "mode": "search",
    "query": "werewolf",
    "startUrls": [
        "https://www.wattpad.com/story/12702726-werewolf-committee"
    ],
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/wattpad-scraper").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 = {
    "mode": "search",
    "query": "werewolf",
    "startUrls": ["https://www.wattpad.com/story/12702726-werewolf-committee"],
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/wattpad-scraper").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 '{
  "mode": "search",
  "query": "werewolf",
  "startUrls": [
    "https://www.wattpad.com/story/12702726-werewolf-committee"
  ],
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/wattpad-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/wattpad-scraper"
        }
    }
}
```

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/3Fcbi1ezrMGHeufZQ/builds/Hh3ECGfndPXml07uG/openapi.json
