# Baidu SERP API - Baidu Search Results Scraper (`s-r/baidu-serp`) Actor

Baidu search results as clean data: title, the real destination URL instead of the Baidu redirect, snippet, source site and date, for Chinese or English keywords. For SEO teams, China market researchers and developers.

- **URL**: https://apify.com/s-r/baidu-serp.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** SEO tools, Marketing, Developer tools
- **Stats:** 2 total users, 1 monthly users, 90.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 per-run start fees

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 SERP API: Baidu search results as structured data

This Baidu SERP API turns any Chinese or English keyword into organic Baidu search results
you can use straight away: one row per result with the title, the **real destination URL**,
the snippet, the source site and the date where Baidu prints one. Use it to track rankings in
China, research a market before you enter it, or feed Baidu results into your own tool.

Chinese and English keywords both work, and they return genuinely different result sets, so
search in the language your audience uses.

### What you get from the Baidu SERP API

- **Real destination URLs.** Every Baidu result links through `baidu.com/link?url=…`, a redirect
  that says nothing about where it goes. Baidu also writes the destination onto the result's own
  container, so `url` is where the result actually points and `baidu_url` is the redirect a
  browser would open. No extra request per row, no unresolved links in your export.
- **Baidu's own properties, flagged.** Baike, Zhidao, Tieba, Wenku and the rest appear throughout
  the organic list. They are real results and dropping them would misrepresent the page, so they
  stay, with `is_baidu_property` set to true. Filter on it for third-party pages only. The ratio is
  itself the finding: a keyword where Baidu's own surfaces take most of the page is a keyword
  you cannot rank on.
- **Continuous rank.** With several pages per keyword, `rank` keeps counting across the whole
  walk, so page two starts where page one stopped. That is what you want when you check where a
  domain sits.

### Baidu SERP API use cases

- **Rank tracking in China.** Run your keywords on a schedule and join the exports on keyword and
  rank to see movement of your domain and of competitors.
- **Market research.** Check what Chinese searchers see for a product category before you enter the
  market, and which sites and Baidu properties dominate it.
- **Content and SEO audits.** Collect titles, snippets and sources for a keyword list to see how
  results are worded and how many are dated.
- **Data pipelines.** Use the dataset API as a Baidu search API for dashboards, spreadsheets or
  LLM research tools, in JSON, CSV or Excel.

### How this compares with other options

The official Baidu search is a website, not a data feed, and the commercial SERP APIs that cover
Baidu bill per search or by monthly plan. This actor charges per delivered result with a small
start fee, needs no account with the engine and no API key of your own, and keeps the output
shape stable. For other engines see the Google, Bing, Yahoo and DuckDuckGo SERP actors; for the
Chinese market beyond search, see the e-commerce actors.

### There is usually no result count

`total_results` is null on most pages, and that is Baidu rather than a gap
here. The current layout prints "found the following results" with no number
at all; only the older layout gives a figure, and where it does you get it.

### Paging

**Pages per keyword** walks further into the results. `rank` is continuous
across the whole walk, so page two starts where page one stopped rather than
back at 1, which is what you want when you are checking where a domain sits.

**Results per page** accepts 10 to 50. Baidu often returns a few more than
asked and sometimes fewer, so trust the rows rather than the request.

### Errors

| Code | Meaning |
|---|---|
| `blocked` | No attempt got a results page back |
| `no_results` | The page was served and matched nothing |
| `bad_input` | No keyword was given |

`blocked` and `no_results` are worth telling apart here more than on most
targets: an empty page from Baidu is far more often about where the request
came from than about the keyword. Raise **Attempts per page** if you see
`blocked`, and try the keyword in Chinese before concluding nothing matches.

### Baidu SERP Scraper input

The input requires `keywords`. The initial query is `价格监控`, and an English
query used with this actor is `price monitoring`. Enter each query on its own
line. Leading and trailing whitespace is removed, and blank lines are ignored.
Repeated keywords remain separate searches, so you can compare their results
without losing entries from your requested sequence.

`pages` defaults to 1 and accepts 1 to 10 pages per keyword. `resultsPerPage`
defaults to 10 and accepts 10 to 50. These values describe how far the actor
walks, while `maxResults` limits the entire dataset across all keywords. Its
default is 200 and the maximum is 5,000. `attempts` defaults to 4 and accepts
1 to 15 attempts for a page that cannot be read. Increasing the result limit
does not guarantee that Baidu has that many distinct results.

An input used for a real run is:

```json
{"keywords":["price monitoring","跨境电商"],"pages":2,"maxResults":35,"attempts":6}
```

### Example Baidu SERP API output

A real row from a run with the keyword `price monitoring`:

```json
{
  "title": "Price Monitoring | Official Portal of the Department of Agriculture",
  "url": "https://www.da.gov.ph/price-monitoring/",
  "baidu_url": "http://www.baidu.com/link?url=-b8BolvSn65xzsjAKxZooY65TPhH7b0JeWsWMzkx-5RbkDJZbd6SXCFPVY-i5iFPeuBQe_qMSyOGTPfK5IV3sq",
  "display_host": "da.gov.ph",
  "source": "菲律宾农业部官网",
  "snippet": "home price monitoring price monitoring weekly average retail prices 2026 weekly average prices date file size september 21-27, 2026 138 kb september 14-20, 2026 126 kb september 7-13, 2026 138 kb august 31-sept 菲律宾农业部官网",
  "published": null,
  "is_baidu_property": false,
  "keyword": "price monitoring",
  "page": 1,
  "rank": 2,
  "total_results": null,
  "position": 2
}
```

### Output and exports

The default dataset contains one row per organic search result. Each row
identifies its `keyword`, `page`, continuous `rank` within that keyword, and
`position` within the whole run. The title, destination `url`, `baidu_url`,
`display_host`, `source`, `snippet`, `published`, `is_baidu_property`, and
`total_results` retain their existing names.

Missing source information is returned as null. This is particularly common
for publication dates and Baidu's total-result estimate. A result without an
explicit destination can still have a useful Baidu redirect link. A source
label is the text Baidu prints for that result; it is separate from the
hostname parsed from the destination URL.

Download the dataset in JSON, CSV, or another export format supported by
Apify. JSON preserves nulls and booleans; spreadsheet tools may display those
values differently. Keep the keyword and rank columns when joining this
export to a previous run. Search results change over time, so use the URL
alongside the title when comparing individual pages.

The key-value store contains a summary with the number of results, distinct
hosts, results on Baidu properties, dated results, and any collection errors.
If a search is unavailable, the errors record explains which query failed.
A partially completed search retains the results that were actually read.
An empty search produces an empty dataset and a successful run with an
explanation; it does not invent results to fill the requested limit.

### Pricing

Pricing is pay per event: $0.002 per run start and $0.0025 per delivered
result. The start event applies even when the query is blank or Baidu
returns no readable results. The result event applies only to rows actually
written to the dataset. An empty dataset therefore has no result charges.

For non-paying Apify users, delivery is limited to ten results per run and
collection respects that limit. Those delivered rows retain the same event
price. Paying users can request the larger limits described above. Apify's
platform usage is separate from the actor's event prices; consult your run
billing details for the full cost.

### Frequently asked questions

#### Can I search in English?

Yes. Chinese and English keywords are accepted. The language of the keyword
can change which websites Baidu returns, so use the wording your audience
searches for when measuring visibility.

#### Why are there fewer rows than resultsPerPage?

Baidu controls the returned results. Entries without a usable title are
skipped, duplicate destinations within a page are merged, and the global
result limit can stop collection before the final page ends. The requested
page size is not a promise of an exact row count.

#### Are Baidu-owned pages excluded?

No. They remain part of the organic result list and are marked with
`is_baidu_property`. Filter that field when you need only external websites.
Keeping the original entries also preserves the ranking you actually saw.

#### Does a missing published value mean the page has no date?

It means the result did not contain a date in the recognised format. Baidu
can omit a date or use a different date representation. The snippet remains
available for your own analysis, and the actor does not infer a publication
date from unrelated numbers.

# Actor input Schema

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

One per line. Chinese or English both work; Baidu indexes both and answers differently for each.

## `pages` (type: `integer`):

How deep to walk each keyword.

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

Baidu accepts 10 to 50 and often returns a few more than asked.

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

Stop after this many rows. Also the cost ceiling for the run.

## `attempts` (type: `integer`):

How often to retry through a fresh exit before giving up on a page. An empty page is usually the exit rather than the keyword.

## Actor input object example

```json
{
  "keywords": [
    "price monitoring",
    "跨境电商"
  ],
  "pages": 1,
  "resultsPerPage": 10,
  "maxResults": 200,
  "attempts": 4
}
```

# Actor output Schema

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

One row per result.

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

Results returned, how many were Baidu's own properties, and how many distinct hosts appeared.

## `errors` (type: `string`):

Keywords that could not be read.

# 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 = {
    "keywords": [
        "价格监控"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/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 = { "keywords": ["价格监控"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/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 '{
  "keywords": [
    "价格监控"
  ]
}' |
apify call s-r/baidu-serp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/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/rQ14NhQtK7Msdh6i2/builds/fvOwIFhJuaLPnNfbK/openapi.json
