# Quora Keyword Search & Author Discovery Scraper (`vexaloom-labs/quora-keyword-search-and-author-discovery-scraper`) Actor

Search Quora by keyword or scrape visibly accessible question, answer, profile, topic, Space, and Post URLs directly, with filters for promoted cards, AI-labeled answers, unanswered questions, and author discovery across your results.

- **URL**: https://apify.com/vexaloom-labs/quora-keyword-search-and-author-discovery-scraper.md
- **Developed by:** [vexaloom-labs](https://apify.com/vexaloom-labs) (community)
- **Categories:** Social media, Lead generation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

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

## Quora Keyword Search & Author Discovery Scraper

Collect public Quora questions, full answers, author profiles, and topics without cookies or logins. Paste question, answer, profile, or topic URLs, or use best-effort keyword discovery with related-question expansion. The default path is HTTP; a residential browser fallback is automatic only after Quora challenges the direct, datacenter, and residential HTTP paths.

### What this actor does

- **Three modes:** `urls` follows pasted Quora links, `search` discovers indexed question links and expands related questions, `authors` builds author profiles from profile or question URLs.
- **Full question context:** title, URL, topics, follower count, answer count, related questions, and the explicit unanswered state.
- **Full answers:** answer text, permalink, author name and profile link, credential, verified badge, upvotes, views, comment count, share count, exact creation date, AI label, and related-answer provenance.
- **Author profiles:** followers, following, answers, questions, posts, content views, join date, credential, location, employment, education, and expertise topics.
- **Honest discovery:** Quora's native search page is gated for anonymous visitors, so keyword mode uses a public web index and reports a clear status row when no indexed matches exist. Related-question expansion is the reliable discovery path.
- **HTTP first, browser last resort:** every page is fetched over HTTP first. Only if Quora challenges the direct, datacenter, and residential HTTP paths does the actor render that page in a real Chromium session through a residential connection. The same parser is used, so the output shape does not change.
- Leaves empty fields out of each row instead of writing guesses or nulls.

### Output per question

- `question_id`, `title`, `question_title`, `url`, `question_url`, `canonical_url`
- `topics[]`, `topic_urls[]`
- `answer_count`, `answer_count_text`, `answer_count_scraped`, `last_answered_at`
- `follow_count`, `follow_count_text`, `follower_count`
- `related_questions[]`, `related_questions_count`
- `question_language`, `answer_pagination_state`
- `discovery_source`, `source_query`, `parent_question_url`
- `access_state`, `scrape_timestamp`, `record_id`

### Output per answer

- `answer_id`, `answer_url`, `answer_text`, `word_count`
- `upvotes` / `upvotes_text`, `view_count` / `view_count_text`
- `comments_count` / `comments_count_text`, `shares_count` / `shares_count_text`
- `created_at`, `answer_created_at`, `answer_timestamp`, `answer_updated_at`
- `author_name`, `author_url`, `author_id`, `author_image_url`, `author_credentials`, `author_is_verified`, `author_is_anonymous`
- `is_ai_answer`, `ai_label_text`, `answer_visibility`, `answer_is_collapsed`
- `answer_is_related`, `source_question_url`, `source_question_title`
- `question_id`, `question_title`, `question_url`
- `media_urls`, `image_urls`, `video_urls`, `outbound_links` (optional)
- `answer_html` (optional), `discovery_source`, `source_url`, `access_state`

### Output per author

- `author_id`, `name`, `profile_url`, `avatar_url`, `credential`, `is_verified`
- `follower_count`, `following_count`, `answer_count`, `question_count`, `post_count`, `content_views`
- `joined_at`, `location`, `employment`, `education`
- `topics[]`, `bio`, `website_url`, `social_links[]`
- `evidence_urls[]`, `evidence_question_urls[]`, `evidence_answer_urls[]`, `evidence_answer_previews[]`

A direct profile URL in `urls` mode emits a `profile` row with the same profile fields. In `authors` mode it emits an `author` row.

### Output per topic

- `topic_id`, `name`, `url`, `follower_count`
- `discovery_source`, `source_url`, `access_state`

### Output per status / manifest

Status rows explain a page that could not be read: `access_state` is one of `not_found`, `removed`, `login_required`, `cloudflare_challenge`, `rate_limited`, `unavailable`, `unsupported_url`, or `discovery_unavailable`. A run-manifest row is written at the end of every run that starts.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `urls` | `urls`, `search`, or `authors` |
| `directUrls` | array | – (prefilled with one Python question) | Question, answer, profile, or topic URLs |
| `searchQueries` | array | – | Keywords or question titles for best-effort discovery (mode=search) |
| `usernames` | array | – | Profile slugs converted to profile URLs |
| `resultTypes` | array | `["question","answer"]` | `question`, `answer`, `profile`, `author`, `topic` |
| `includeAnswers` | boolean | `true` | Emit answers from question pages |
| `maxAnswersPerQuestion` | integer | `20` | Answer cap per question (0–500) |
| `includeRelatedQuestions` | boolean | `false` | Follow related-question links |
| `maxRelatedQuestions` | integer | `15` | Cap per question; 0 keeps all observed |
| `includeAuthorProfiles` | boolean | `true` | Enrich discovered authors with profile stats |
| `maxAuthors` | integer | `100` | Author-row cap |
| `minAnswerUpvotes` | integer | `0` | Drop answers below this explicit upvote count |
| `filterAiAnswers` | string | `include` | `include`, `exclude`, or `only` |
| `answerSortOrder` | string | `observed` | `observed`, `upvotes_desc`, or `newest` |
| `onlyUnanswered` | boolean | `false` | Keep only questions with an explicit zero answer count |
| `includeMedia` | boolean | `false` | Retain answer image/video links |
| `includeOutboundLinks` | boolean | `false` | Retain external links in answers |
| `includeAnswerHtml` | boolean | `true` | Retain a simple HTML rendering of answers |
| `includeProfileSensitiveFields` | boolean | `true` | Include location, employment, education, join date |
| `includeSocialLinks` | boolean | `true` | Include profile website/social links |
| `maxItems` | integer | `200` | Total real-row cap |
| `maxItemsPerSource` | integer | `0` | Per-URL/keyword cap (0 = no cap) |
| `includeFieldEvidence` | boolean | `true` | Add `field_sources` and `fields_present` |

The saved prefill is one question with `maxAnswersPerQuestion: 2` and `maxItems: 3`, so the first run returns three real rows.

### Examples

#### A question with many answers

```json
{
  "mode": "urls",
  "directUrls": ["https://www.quora.com/What-is-Python-primarily-used-for"],
  "resultTypes": ["question", "answer"],
  "maxAnswersPerQuestion": 50
}
```

#### A profile and its stats

```json
{
  "mode": "authors",
  "directUrls": ["https://www.quora.com/profile/Adam-DAngelo"],
  "resultTypes": ["author"]
}
```

#### Expand related questions from one seed

```json
{
  "mode": "search",
  "directUrls": ["https://www.quora.com/What-is-machine-learning"],
  "includeRelatedQuestions": true,
  "maxRelatedQuestions": 10,
  "maxItems": 100
}
```

#### Best-effort keyword discovery

```json
{
  "mode": "search",
  "searchQueries": ["remote work productivity"],
  "includeRelatedQuestions": true,
  "maxItems": 50
}
```

### Use cases

- **Market and product research** — collect complete answer threads with engagement metrics.
- **Expert sourcing** — turn answer authors into a profile list with follower and answer counts.
- **Content gap analysis** — find questions with zero answers in a niche.
- **AI-answer auditing** — separate explicitly AI-labelled answers from human answers.
- **Knowledge-base building** — export clean question/answer pairs with source URLs and dates.

### FAQ

#### Does this actor need cookies or a login?

No. It reads public question, answer, profile, and topic pages without an account. There is no cookie or proxy field to configure.

#### Why can't I search Quora by keyword reliably?

Quora's own search page is gated for anonymous visitors, and the actor never calls Quora's `/search?q=` endpoint. It uses a public web index for keyword discovery and expands related questions from any question it reaches. When no indexed matches exist, it writes a `discovery_unavailable` status row and does not invent results.

#### How many answers can I get?

All answers that Quora exposes through its answer feed, up to `maxAnswersPerQuestion`. The actor follows the answer cursor until your cap or the end of the feed. Popular questions can contain thousands of answers; set a cap for the first run.

#### Why is an answer marked as related?

Quora sometimes shows answers written for a merged or equivalent question. Those rows carry `answer_is_related: true` and `source_question_url` / `source_question_title`, so the answer is not misattributed to the page you opened.

#### Why are some fields missing on some rows?

Quora only publishes a credential, location, employment, education, or bio for some users. Missing values are omitted, never guessed. Question creation dates and question view counts are not published on the public question page and are not emitted.

#### Can I get comment text?

No. Quora publishes the comment count with each answer, but not the comment bodies on the public page. The actor returns the count only.

#### What does "best-effort" mean for keyword discovery?

It means the actor tries a public index first and tells you when that index has no matches. It never re-labels related questions or unrelated pages as keyword search results.

#### What happens if Quora challenges the page?

The actor first tries its fast HTTP path, then datacenter and residential HTTP. If all three are challenged, it renders that page in a real browser through its residential connection and parses the same data. If even that is blocked, the page is reported as a `cloudflare_challenge` status row. The browser fallback is slower, uses more memory, and incurs residential data transfer for the pages that need it; it only runs after direct, datacenter, and residential HTTP are challenged.

#### Is this affiliated with Quora?

No. This is an independent, third-party actor that reads public Quora pages. It is not affiliated with or endorsed by Quora.

### Limitations

- Native Quora keyword search is unavailable anonymously; keyword discovery depends on a public web index.
- Comment bodies, question creation dates, question view counts, topic question feeds, and full profile answer lists are not available from the public page.
- Topic pages expose the topic name and follower count; descriptions and question counts are omitted when Quora does not publish them.
- Very large answer threads are bounded by `maxAnswersPerQuestion` and `maxItems`.
- A page that is removed, private, or behind a login wall is reported as a status row, not fabricated data.
- Challenge recovery uses a real browser as a last resort, so it is slower, uses more memory, and incurs residential data transfer for the pages that need it.

# Actor input Schema

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

What to scrape. `urls` follows pasted Quora links. `search` discovers indexed question links for your keywords and expands related questions. `authors` builds author profiles from pasted profile or question URLs.

## `directUrls` (type: `array`):

Paste question, answer, profile, or topic URLs. Language subdomains such as es.quora.com are accepted. Invalid links are reported as status rows.

## `searchQueries` (type: `array`):

Best-effort keyword discovery. Quora's own search page is gated for anonymous visitors, so results depend on the public web index; a run with no indexed matches returns a clear status row instead of invented results.

## `usernames` (type: `array`):

Quora profile slugs, with or without a leading @ or trailing slash. Converted to profile URLs and merged with Quora URLs.

## `resultTypes` (type: `array`):

Which entity rows to emit. Status and run-manifest rows are always written when relevant.

## `includeAnswers` (type: `boolean`):

Emit answer rows and fetch answers beyond the first visible cards on question pages.

## `maxAnswersPerQuestion` (type: `integer`):

Answer cap for each question URL. Zero emits no answers from question pages.

## `includeRelatedQuestions` (type: `boolean`):

Follow the related-question links on each question page and scrape those questions too. This is the reliable discovery path when keyword search is gated.

## `maxRelatedQuestions` (type: `integer`):

Related questions retained per question page and used as discovery seeds. Zero keeps all observed related questions.

## `includeAuthorProfiles` (type: `boolean`):

Open each discovered author's profile to add followers, following, answer/question counts, views, join date, and credential.

## `maxAuthors` (type: `integer`):

Maximum unique author rows emitted from answer evidence.

## `minAnswerUpvotes` (type: `integer`):

Drop answers below this upvote count. Answers with no explicit upvote count are excluded when this is above zero.

## `filterAiAnswers` (type: `string`):

Include all answers, exclude answers explicitly labelled as AI, or keep only those AI-labelled answers.

## `answerSortOrder` (type: `string`):

Keep Quora's observed order, or sort by explicit upvotes or creation time.

## `includeMedia` (type: `boolean`):

Retain image and video links embedded in answer content.

## `includeOutboundLinks` (type: `boolean`):

Retain external links embedded in answer content.

## `includeAnswerHtml` (type: `boolean`):

Retain a simple HTML rendering of each answer alongside its plain text.

## `includeProfileSensitiveFields` (type: `boolean`):

Include location, employment, education, and join date on profile and author rows.

## `includeSocialLinks` (type: `boolean`):

Include website and social links found on a profile.

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

Hard cap on real data rows across the run. Status and manifest rows do not consume the cap.

## `maxItemsPerSource` (type: `integer`):

Cap real rows emitted from each URL or keyword. Zero means no per-source cap.

## `includeFieldEvidence` (type: `boolean`):

Add field_sources and fields_present metadata so each value can be traced to the page payload.

## `onlyUnanswered` (type: `boolean`):

Keep only questions whose explicit answer count is exactly zero. Unknown counts are excluded.

## Actor input object example

```json
{
  "mode": "urls",
  "directUrls": [
    "https://www.quora.com/What-is-Python-primarily-used-for"
  ],
  "searchQueries": [],
  "usernames": [],
  "resultTypes": [
    "question",
    "answer"
  ],
  "includeAnswers": true,
  "maxAnswersPerQuestion": 2,
  "includeRelatedQuestions": false,
  "maxRelatedQuestions": 15,
  "includeAuthorProfiles": true,
  "maxAuthors": 20,
  "minAnswerUpvotes": 0,
  "filterAiAnswers": "include",
  "answerSortOrder": "observed",
  "includeMedia": false,
  "includeOutboundLinks": false,
  "includeAnswerHtml": true,
  "includeProfileSensitiveFields": true,
  "includeSocialLinks": true,
  "maxItems": 3,
  "maxItemsPerSource": 0,
  "includeFieldEvidence": true,
  "onlyUnanswered": false
}
```

# Actor output Schema

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

Dataset containing question, answer, profile, author, topic, status, and manifest rows.

# 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": "urls",
    "directUrls": [
        "https://www.quora.com/What-is-Python-primarily-used-for"
    ],
    "searchQueries": [],
    "resultTypes": [
        "question",
        "answer"
    ],
    "includeAnswers": true,
    "maxAnswersPerQuestion": 2,
    "includeRelatedQuestions": false,
    "maxRelatedQuestions": 0,
    "includeAuthorProfiles": false,
    "maxAuthors": 20,
    "filterAiAnswers": "include",
    "answerSortOrder": "observed",
    "includeMedia": false,
    "includeOutboundLinks": false,
    "includeAnswerHtml": false,
    "includeProfileSensitiveFields": true,
    "includeSocialLinks": true,
    "maxItems": 3,
    "maxItemsPerSource": 0,
    "includeFieldEvidence": true,
    "onlyUnanswered": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("vexaloom-labs/quora-keyword-search-and-author-discovery-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": "urls",
    "directUrls": ["https://www.quora.com/What-is-Python-primarily-used-for"],
    "searchQueries": [],
    "resultTypes": [
        "question",
        "answer",
    ],
    "includeAnswers": True,
    "maxAnswersPerQuestion": 2,
    "includeRelatedQuestions": False,
    "maxRelatedQuestions": 0,
    "includeAuthorProfiles": False,
    "maxAuthors": 20,
    "filterAiAnswers": "include",
    "answerSortOrder": "observed",
    "includeMedia": False,
    "includeOutboundLinks": False,
    "includeAnswerHtml": False,
    "includeProfileSensitiveFields": True,
    "includeSocialLinks": True,
    "maxItems": 3,
    "maxItemsPerSource": 0,
    "includeFieldEvidence": True,
    "onlyUnanswered": False,
}

# Run the Actor and wait for it to finish
run = client.actor("vexaloom-labs/quora-keyword-search-and-author-discovery-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": "urls",
  "directUrls": [
    "https://www.quora.com/What-is-Python-primarily-used-for"
  ],
  "searchQueries": [],
  "resultTypes": [
    "question",
    "answer"
  ],
  "includeAnswers": true,
  "maxAnswersPerQuestion": 2,
  "includeRelatedQuestions": false,
  "maxRelatedQuestions": 0,
  "includeAuthorProfiles": false,
  "maxAuthors": 20,
  "filterAiAnswers": "include",
  "answerSortOrder": "observed",
  "includeMedia": false,
  "includeOutboundLinks": false,
  "includeAnswerHtml": false,
  "includeProfileSensitiveFields": true,
  "includeSocialLinks": true,
  "maxItems": 3,
  "maxItemsPerSource": 0,
  "includeFieldEvidence": true,
  "onlyUnanswered": false
}' |
apify call vexaloom-labs/quora-keyword-search-and-author-discovery-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vexaloom-labs/quora-keyword-search-and-author-discovery-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/kBf4VDxTBbjxk50DV/builds/JWoVhbBdDSTo9DNhE/openapi.json
