# Bing Search Scraper – SERP Results (`datascraperes/bing-search-scraper`) Actor

Scrape Bing organic search results for any keyword. Get rank, URLs, domains, snippets, dates, sitelinks and SERP features across 50 countries with pagination.

- **URL**: https://apify.com/datascraperes/bing-search-scraper.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 82 total users, 30 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.45 / 1,000 organic 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

Collect structured Bing organic search results for one query or a large keyword list and receive export-ready Dataset items with ranking and localization context. **Pay per delivered organic result**, with lower unit prices for higher Apify Store tiers.

### What this Actor does

The Actor searches Bing across 50 supported country markets, normalizes and deduplicates queries, follows result pages within the configured limits, and removes duplicate organic URLs for each query. Each delivered organic result is saved as one Dataset item with query, page, position, URL, snippet, and collection metadata.

### Use cases

- Track organic rankings across keywords and countries.
- Compare competitors, domains, titles, and snippets in search results.
- Build keyword-research and content-planning datasets.
- Compare visibility across Google, Bing, Yahoo, and DuckDuckGo.

### How to use

1. Add one or more search queries.
2. Select a country market and SafeSearch level.
3. Choose the result and page limits.
4. Start the Actor and export the Dataset when it finishes.

While the Actor runs, the Apify run status and log show clear progress milestones for the query batch and the organic results delivered.

#### Reduce run cost with batches

For large keyword lists, run smaller batches from the same `queries` list and keep the same search settings. Batching can reduce peak run resources and simplify retries; it does not change the dataset fields or the per-query result format. Each run supports up to 1,000 unique queries.

### Input

Submit 1–1,000 unique queries, each up to 500 characters. Use only the documented input fields. `maxResultsPerQuery` accepts 1–50, `pagesPerQuery` accepts 1–20, `country` selects one of 50 markets, and `safeSearch` supports Strict, Moderate, or Off. Optional switches add query-level SERP features or keep ads in a separate field. Duplicate and blank queries are removed automatically.

This exact input produced the complete output below:

```json
{
  "queries": [
    "apify web scraping"
  ],
  "maxResultsPerQuery": 10,
  "pagesPerQuery": 1,
  "country": "US",
  "safeSearch": "Moderate",
  "includeSerpFeatures": true,
  "includeAds": false
}
```

### Output

Each charged `organicResult` row is one organic result with query context, country and market, position within its Bing result page, page number, title, destination URL, source domain, display URL, description, optional date, sitelinks, rich facts, pagination status, and collection timestamp. Optional SERP features remain query-level context and advertisements are never mixed into organic rows. A free `queryStatus` row can report query-level errors or zero-result outcomes.

This is the complete first Dataset item from a real successful run:

```json
{
  "type": "organicResult",
  "query": "apify web scraping",
  "queryId": "9c486230ff7108730c18f1bc",
  "country": "US",
  "market": "en-US",
  "pagesRequested": 1,
  "pagesFetched": 1,
  "paginationStoppedReason": "max_results_reached",
  "organicResultsFound": 10,
  "serpFeatures": {
    "estimatedResultsText": "About 30,000 results",
    "relatedSearches": [],
    "peopleAlsoAsk": [],
    "answerCards": [],
    "knowledgePanel": {
      "title": null,
      "description": null
    }
  },
  "fetchedAt": "2026-09-21T07:42:36.219714+00:00",
  "position": 1,
  "title": "Ноутбукдля программированияв2026году ...",
  "url": "https://rest.kyiv.ua/ru/blog/kak-pravilno-vybrat-noutbuk-dlya-programmirovaniya-v-2026-go-955",
  "sourceDomain": "rest.kyiv.ua",
  "displayUrl": "https://rest.kyiv.ua › ru › blog",
  "description": "Jul 12, 2026· Как выбрать ноутбук для программирования в 2026 году? Сравниваем процессор, ОЗУ, SSD, экран, ОС и …",
  "date": "Jul 12, 2026",
  "sitelinks": [],
  "richFacts": [],
  "page": 1
}
```

### Pricing

One delivered `organicResult` row is one billable `organic-result` event. The price depends on the user's Apify Store plan:

| Apify plan | Price per result | Price per 1,000 results |
| --- | ---: | ---: |
| Free | $0.0006 | $0.60 |
| Bronze | $0.00055 | $0.55 |
| Silver | $0.0005 | $0.50 |
| Gold | $0.00045 | $0.45 |
| Platinum | $0.00045 | $0.45 |
| Diamond | $0.00045 | $0.45 |

Empty queries, duplicates, failed requests, status records, and run summaries are not charged as organic results. Apify platform usage can still apply according to your plan.

### Related Actors

| Actor | Best for |
|---|---|
| [Google SERP Scraper API – Search Results Scraper](https://apify.com/datascraperes/google-serp-scraper) | Comparing Google organic rankings for the same queries. |
| [DuckDuckGo Search Scraper — Organic SERP API](https://apify.com/datascraperes/duckduckgo-search-results-scraper) | Collecting privacy-focused DuckDuckGo organic results with region controls. |
| [Yahoo Search Results Scraper](https://apify.com/datascraperes/yahoo-search-scraper) | Comparing localized Yahoo rankings and snippets. |

### Limits and data quality

Temporary source issues are retried within bounded limits. If a page remains unavailable or repeats earlier results, the Actor saves the results already collected and finishes with a **partial-results notice**, rather than failing the entire run for that source issue. Check the free `queryStatus` rows for affected queries. Results from incomplete queries are preserved without an organic-result charge. A successful run status can therefore include partial collection; it does not guarantee that every query reached its requested limits.

When the execution time is nearly exhausted, the Actor stops starting queries and saves a partial summary. An interrupted run can resume from its saved delivery records.

Unconfirmed data delivery, billing errors, invalid input, or internal errors can still fail the run. Saved data remains available. Use the same input and storage when resuming interrupted delivery; use a new run when changing search settings.

Bing can return fewer results than requested, repeat domains, omit dates or snippets, or change rankings between runs. Pagination stops when the result limit is reached, no new organic URLs appear, or the requested page boundary is met. Configured limits are maxima, not guaranteed counts, and current search-engine availability determines what can be delivered.

### Frequently asked questions

#### What does `position` mean?

`position` is the organic rank within the Bing result page recorded in `page`. The Actor also removes duplicate destination URLs across pages, so the number of delivered rows can be lower than the requested maximum.

#### Why did I receive fewer results than requested?

The source may expose fewer unique organic URLs, pagination may end, duplicate destinations may be removed, or a temporary restriction may stop the query. Review the pagination and status fields in the result.

#### Can I run the same queries on a schedule?

Yes. Apify schedules can repeat the Actor, and each Dataset preserves its collection timestamp for comparison.

### Responsible use

Use search-result data for lawful purposes. Respect the search engine's terms, applicable privacy and data-protection laws, copyright, and the rights of listed websites. Rankings and snippets are observations at collection time, not permanent facts.

### Support

Open an issue in the Actor's **Issues** tab with the run ID, affected query, localization settings, and expected result. Never include API tokens, passwords, or private credentials.

[Web guide, API examples and sample dataset on GitHub](https://github.com/datacrawler-edu/bing-search-scraper-python)

# Actor input Schema

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

One query per item. Duplicates and blank values are removed.

## `maxResultsPerQuery` (type: `integer`):

1-50 organic results per query in total, across all requested pages.

## `pagesPerQuery` (type: `integer`):

1-20 Bing result pages. The actor stops early when Bing returns no new organic URLs, preventing duplicate output.

## `country` (type: `string`):

The actor automatically selects the matching Bing interface and results market.

## `safeSearch` (type: `string`):

Bing SafeSearch setting.

## `includeSerpFeatures` (type: `boolean`):

Extract optional query-level blocks such as estimated results, related searches, answer cards and knowledge-panel summaries.

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

Extract ads into a separate field. Ads are never mixed with organic results.

## Actor input object example

```json
{
  "queries": [
    "apify web scraping"
  ],
  "maxResultsPerQuery": 10,
  "pagesPerQuery": 1,
  "country": "US",
  "safeSearch": "Moderate",
  "includeSerpFeatures": true,
  "includeAds": false
}
```

# Actor output Schema

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

The default dataset containing one item per delivered organic Bing result and free query status diagnostics.

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

The SUMMARY record with query, pagination, delivery and charged-result totals for this run.

# 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": [
        "apify web scraping"
    ],
    "maxResultsPerQuery": 10,
    "pagesPerQuery": 1,
    "country": "US",
    "safeSearch": "Moderate",
    "includeSerpFeatures": true,
    "includeAds": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/bing-search-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 = {
    "queries": ["apify web scraping"],
    "maxResultsPerQuery": 10,
    "pagesPerQuery": 1,
    "country": "US",
    "safeSearch": "Moderate",
    "includeSerpFeatures": True,
    "includeAds": False,
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/bing-search-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 '{
  "queries": [
    "apify web scraping"
  ],
  "maxResultsPerQuery": 10,
  "pagesPerQuery": 1,
  "country": "US",
  "safeSearch": "Moderate",
  "includeSerpFeatures": true,
  "includeAds": false
}' |
apify call datascraperes/bing-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascraperes/bing-search-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/gODiWbmpvdzmF9x2r/builds/aAuOcWGdzLb73pm0V/openapi.json
