# Baidu Search Scraper — China SERP Results API (`khadinakbar/scrape-baidu-serp`) Actor

Scrape Baidu (百度) search results pages — organic ranks, titles, real URLs, snippets, ads, related queries, and answer boxes. China Residential proxy recommended. MCP-ready.

- **URL**: https://apify.com/khadinakbar/scrape-baidu-serp.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** SEO tools, AI, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 baidu serp pages

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Baidu Search Scraper — China SERP Results API

**Scrape Baidu (百度) search results** into structured JSON for China SEO rank tracking, competitor research, and AI agents. One dataset row per SERP page with organic ranks, titles, destination URLs, snippets, ads, related searches, and answer boxes.

Built for Apify: run via Console, API, schedules, or MCP (`apify--scrape-baidu-serp`). Pay per SERP page + platform usage.

### Best fit for this Actor

- Use this Actor when you need structured Baidu SERP rows for Chinese keyword rankings, competitor visibility, or agent enrichment.
- Prefer Simplified Chinese queries and Apify Residential proxies with country **CN** for stable yield.
- Start with the Console prefill (`苹果手机`), confirm organic positions and `source=baidu-native`, then raise `maxPagesPerQuery` for deeper pages.
- For Google (global) SERP workflows, continue with [Google SERP Scraper](https://apify.com/khadinakbar/scrape-google-serp) when you need organic Google results outside Baidu.
- For a fuller Google SERP surface (ads, AI Overviews, PAA, local pack), then use [Google SERP All-in-One](https://apify.com/khadinakbar/google-serp-all-in-one-scraper).

### Practical scenario

A China SEO analyst tracks `苹果手机` and `北京旅游` weekly. They paste both queries, keep `maxPagesPerQuery` at 1, enable `resolveRealUrls`, and download the dataset. Each row gives organic position, title, real destination URL, ads, and related searches so the team can spot rank moves and competitor ad presence before updating a client report.

### Quick start input

```json
{
  "queries": ["苹果手机", "北京旅游"],
  "maxPagesPerQuery": 1,
  "device": "desktop",
  "includeAds": true,
  "includeRelatedSearches": true,
  "resolveRealUrls": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "CN"
  }
}
```

Provide keyword queries, direct `baidu.com/s?wd=...` URLs via `startUrls`, or both. At least one is required. Prefer Simplified Chinese keywords.

### What data you get

| Field | Description |
|-------|-------------|
| `search_query` | Keyword you searched |
| `results_page` / `pn_offset` | Page number and Baidu `pn` offset |
| `organic_results[]` | position, title, url, baidu\_redirect\_url, display\_url, domain, snippet, date |
| `ad_results[]` | Commercial / 广告 blocks when present |
| `related_searches[]` | 相关搜索 suggestions |
| `answer_box` | 百科 / exact-answer box when present |
| `total_results_hint` | Baidu result-count hint text when available |
| `source` | Always `baidu-native` on this build |

#### Example output (one SERP page)

```json
{
  "search_query": "苹果手机",
  "results_page": 1,
  "pn_offset": 0,
  "device": "desktop",
  "organic_results": [
    {
      "position": 1,
      "title": "苹果手机官网",
      "url": "https://www.apple.com.cn/",
      "snippet": "官方介绍…",
      "domain": "www.apple.com.cn"
    }
  ],
  "ad_results": [],
  "related_searches": ["苹果手机报价", "华为手机"],
  "answer_box": null,
  "source": "baidu-native",
  "scraped_at": "2026-09-17T12:00:00.000Z"
}
```

`OUTPUT` and `RUN_SUMMARY` in the default key-value store hold `outcome`, `itemsPushed`, and charged event counts. Download the dataset as JSON, CSV, Excel, or HTML.

### How to use

1. Open the Actor in Apify Console
2. Enter Simplified Chinese queries (e.g. `苹果手机`) or paste `baidu.com/s?wd=...` URLs
3. Keep **Proxy** on Apify Residential + country **CN**
4. Start the Actor and download JSON / CSV from the dataset

### Pricing

This Actor uses **Pay per event** plus Apify **platform usage**. The live Pricing tab is the current source of truth for billing details.

| Event | Price |
|-------|-------|
| Actor start | $0.00005 |
| `serp-page` (primary) | **$0.015** per successful Baidu results page |

A one-query, one-page sample with one accepted row is one `serp-page` event plus start and platform usage. Pages that return no parseable SERP skip the primary event.

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~scrape-baidu-serp/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries":["苹果手机"],"maxPagesPerQuery":1,"resolveRealUrls":true,"proxyConfiguration":{"useApifyProxy":true,"apifyProxyGroups":["RESIDENTIAL"],"apifyProxyCountry":"CN"}}'
```

CLI alternative:

```bash
apify call khadinakbar/scrape-baidu-serp --input='{"queries":["苹果手机"],"maxPagesPerQuery":1}'
```

### Use with AI agents through Apify MCP

> Scrape Baidu SERP for 苹果手机. Return organic\_results with position, title, url, and snippet. Read the dataset overview view and OUTPUT.outcome after the run. Budget: one page is about $0.015 event plus Residential CN platform usage. Scope: public Baidu search HTML only. Provenance: source equals baidu-native with scraped\_at.

Connect via <https://mcp.apify.com>. MCP tool: `apify--scrape-baidu-serp` — pass `queries` (or aliases `query` / `keywords`). Keep `maxConcurrency` low on the first call.

### Best results

- Prefer **Simplified Chinese** keywords for China SEO intent
- Use **Residential CN** proxies; non-CN routes often challenge more often
- Keep `maxConcurrency` low (one or two workers) while confirming yield
- Set `resolveRealUrls: false` when Baidu redirect links are enough (faster, less proxy transfer)
- Confirm `OUTPUT.outcome` and `itemsPushed` before treating an empty dataset as finished work

### Builder's note

I found that Baidu mobile HTML on `m.baidu.com` was chronically challenge-heavy from Apify Residential, so this build keeps a single `www.baidu.com/s` path and only swaps the User-Agent for `device=mobile`. I also found that Baidu pagination uses `pn = (page - 1) * rn` rather than a page index, and that coupling `Actor.charge('serp-page')` to each validated page write keeps billing aligned with useful SERP rows.

### Responsible use

Use only for lawful collection and analysis of public Baidu search pages you are authorized to access. Follow applicable laws and Baidu’s terms. Baidu and 百度 are trademarks of Baidu, Inc. This independent Actor is not affiliated with, associated with, or endorsed by Baidu Inc.

### Support

Open an issue on the Actor’s Issues tab for feedback or custom workflow help.

# Actor input Schema

## `queries` (type: `array`):

Use this when the user provides Baidu keywords. Prefer Simplified Chinese terms for best yield (e.g. 苹果手机). Each query produces one dataset row per results page. Do not put baidu.com/s URLs here — use startUrls.

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

Use when the user pastes a Baidu search URL such as https://www.baidu.com/s?wd=.... Pagination and language are taken from the URL. Prefer queries for plain keywords.

## `maxPagesPerQuery` (type: `integer`):

How many Baidu result pages to scrape per query. Page 1 = pn=0, page 2 = pn=10 when resultsPerPage=10. Each successful page is one serp-page billing event.

## `resultsPerPage` (type: `integer`):

Baidu rn parameter. Default 10. Baidu often ignores values above 10–50.

## `device` (type: `string`):

desktop and mobile both use www.baidu.com/s; mobile swaps in a mobile User-Agent (m.baidu path dropped for yield).

## `languageFilter` (type: `string`):

Bias Baidu toward Simplified or Traditional Chinese results, or leave any.

## `timeRange` (type: `string`):

Optional Baidu recency filter via gpc (day / week / month / year).

## `includeAds` (type: `boolean`):

Include Baidu commercial/ad blocks (广告) in ad\_results when present.

## `includeRelatedSearches` (type: `boolean`):

Extract 相关搜索 suggestions from the bottom of the SERP into related\_searches.

## `includeAnswerBox` (type: `boolean`):

Extract Baidu answer/百科/exact-QA boxes when present into answer\_box.

## `resolveRealUrls` (type: `boolean`):

Follow baidu.com/link?url= redirects to the destination URL. Uses extra proxy requests; disable to keep redirect URLs only.

## `maxConcurrency` (type: `integer`):

Parallel Baidu requests. Keep low (1–2) to reduce captchas. Max 5.

## `maxTotalChargeUsd` (type: `number`):

Optional hard cost precheck. If worst-case serp-page charges exceed this amount, the run exits INVALID\_INPUT without scraping.

## `proxyConfiguration` (type: `object`):

Use Apify Residential with country China (CN). Datacenter and non-CN IPs are frequently blocked by Baidu.

## Actor input object example

```json
{
  "queries": [
    "苹果手机",
    "北京旅游"
  ],
  "startUrls": [],
  "maxPagesPerQuery": 1,
  "resultsPerPage": 10,
  "device": "desktop",
  "languageFilter": "any",
  "timeRange": "any",
  "includeAds": true,
  "includeRelatedSearches": true,
  "includeAnswerBox": true,
  "resolveRealUrls": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CN"
  }
}
```

# Actor output Schema

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

Dataset items with organic results, ads, related searches, and answer boxes.

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

Run outcome, itemsPushed, billing counters, and warnings.

## `runSummary` (type: `string`):

Machine-readable RUN\_SUMMARY mirroring OUTPUT.

# 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 = {
    "queries": [
        "苹果手机",
        "北京旅游"
    ],
    "maxPagesPerQuery": 1,
    "resultsPerPage": 10,
    "device": "desktop",
    "languageFilter": "any",
    "timeRange": "any",
    "includeAds": true,
    "includeRelatedSearches": true,
    "includeAnswerBox": true,
    "resolveRealUrls": true,
    "maxConcurrency": 2,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "CN"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/scrape-baidu-serp").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 = {
    "queries": [
        "苹果手机",
        "北京旅游",
    ],
    "maxPagesPerQuery": 1,
    "resultsPerPage": 10,
    "device": "desktop",
    "languageFilter": "any",
    "timeRange": "any",
    "includeAds": True,
    "includeRelatedSearches": True,
    "includeAnswerBox": True,
    "resolveRealUrls": True,
    "maxConcurrency": 2,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "CN",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/scrape-baidu-serp").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 '{
  "queries": [
    "苹果手机",
    "北京旅游"
  ],
  "maxPagesPerQuery": 1,
  "resultsPerPage": 10,
  "device": "desktop",
  "languageFilter": "any",
  "timeRange": "any",
  "includeAds": true,
  "includeRelatedSearches": true,
  "includeAnswerBox": true,
  "resolveRealUrls": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CN"
  }
}' |
apify call khadinakbar/scrape-baidu-serp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/scrape-baidu-serp"
        }
    }
}
```

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/32M10u6vAZxB6uFaZ/builds/skUiVzZMUMbeQeWyJ/openapi.json
