# Bing organic results

Canonical page: https://agentsky.dev/tools/dataforseo/serp_bing_organic_live
JSON record: https://gateway.agentsky.dev/v1/endpoints/dataforseo/serp_bing_organic_live

Bing organic results is a tool from DataForSEO, callable through the AgentSky API as dataforseo/serp_bing_organic_live and billed per call (—).

Runs a live query against the second-largest general web search engine and returns the whole results page as structured data. As with the primary engine, the response is not limited to standard web results: answer boxes, featured snippets, related questions, local packs, image and video blocks, shopping carousels, and AI overviews all come back typed and ranked. This is the natural way to measure how visibility for the same query differs between the two major engines.

One results page, broken into typed and ranked elements with their titles, URLs, domains, and descriptions.

## Facts

- **Id:** `dataforseo/serp_bing_organic_live`
- **Provider:** DataForSEO
- **Kind:** tool
- **Billed per:** call
- **Timeout:** 3 min
- **Max request:** 1 MB

## Call it

`POST https://gateway.agentsky.dev/v1/run` with `{"provider": "dataforseo", "endpoint": "serp_bing_organic_live", "input": {…}}` and `Authorization: Bearer $AGENTSKY_API_KEY`.

### Input fields

| Field | Type | Required | Description |
|---|---|---|---|
| `keyword` | string | yes | Keyword. |
| `location_code` | integer | no | Search engine location code. Required if you don't specify location_name or location_coordinate. |
| `language_code` | string | no | Search engine language code. Required if you don't specify language_name. |
| `location_name` | string | no | Full name of search engine location. Required if you don't specify location_code or location_coordinate. |
| `language_name` | string | no | Full name of search engine language. Required if you don't specify language_code. |
| `location_coordinate` | string | no | GPS coordinates of a location. Required if you don't specify location_name or location_code. |
| `depth` | integer | no | How many results to parse. Default: 10. Max: 200. |
| `device` | string | no | Which device to emulate. Allowed: desktop, mobile. Default: "desktop". |
| `target` | string | no | Only return results from this domain, written without a scheme or `www`. |

## Example

### curl

```bash
# Set once per job; reuse this key and the identical body after a timeout.
: "${AGENTSKY_IDEMPOTENCY_KEY:?Set a unique, saved key for this job}"
curl --fail-with-body https://gateway.agentsky.dev/v1/run \
  -H "authorization: Bearer $AGENTSKY_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $AGENTSKY_IDEMPOTENCY_KEY" \
  -d '{"provider":"dataforseo","endpoint":"serp_bing_organic_live","input":{"language_code":"en","location_code":2840,"keyword":"flight ticket new york san francisco"}}'
# If status is READY/RUNNING, poll GET /v1/runs/{runId} with the same API key.
```

### JavaScript

```js
// Node.js 20+. Save one unique key per job; reuse it with the identical body.
const key = process.env.AGENTSKY_IDEMPOTENCY_KEY;
if (!key || !process.env.AGENTSKY_API_KEY) {
  throw new Error("Set AGENTSKY_API_KEY and a saved AGENTSKY_IDEMPOTENCY_KEY first");
}
const base = "https://gateway.agentsky.dev";
const headers = {
  authorization: `Bearer ${process.env.AGENTSKY_API_KEY}`,
  "content-type": "application/json",
  "Idempotency-Key": key,
};
const body = JSON.stringify({
  "provider": "dataforseo",
  "endpoint": "serp_bing_organic_live",
  "input": {
    "language_code": "en",
    "location_code": 2840,
    "keyword": "flight ticket new york san francisco"
  }
});
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function request(path, options = {}) {
  for (let attempt = 0; attempt < 3; attempt++) {
    let response;
    let data;
    try {
      response = await fetch(base + path, {
        ...options, headers, signal: AbortSignal.timeout(180_000),
      });
      const text = await response.text();
      try { data = JSON.parse(text); } catch { /* Proxy timeouts may return HTML. */ }
    } catch (error) {
      if (attempt === 2) throw error; // Resume with the same key and body.
      await sleep(2000);
      continue;
    }
    // Failed runs can have non-2xx HTTP status. Never regenerate them automatically.
    if (data?.runId && data?.status) return data;
    if (response.ok && data) throw new Error("Unexpected response: missing runId/status");
    if (attempt < 2 && (response.status >= 500 || response.status === 408 || response.status === 429)) {
      await sleep(2000);
      continue; // POST retries keep the original key and body.
    }
    throw new Error(`HTTP ${response.status}: ${JSON.stringify(data ?? "Non-JSON response; retry with the same key and body")}`);
  }
}

let run = await request("/v1/run", { method: "POST", body });
console.log("Save runId:", run.runId);
const deadline = Date.now() + 30 * 60_000;
while (["READY", "RUNNING"].includes(run.status)) {
  if (Date.now() >= deadline) {
    throw new Error(`Still pending: poll /v1/runs/${run.runId} later; do not create a new job`);
  }
  await sleep(5000);
  run = await request(`/v1/runs/${encodeURIComponent(run.runId)}`);
}
console.log("Status:", run.status, "Charge:", run.price?.amount);
if (run.status !== "COMPLETED") {
  throw new Error(`Run ${run.runId}: ${JSON.stringify(run.error ?? run.status)}`);
}
console.log(run.output); // Output shape depends on the endpoint.
// READY/RUNNING price is provisional. Use the terminal receipt for reconciliation.
```

## Pricing

— per call

Reported usage is billed under your account plan. Read the final customer charge from price.amount.value after the run finishes. A RUNNING response is not the final bill.

## Questions

### What does Bing organic results do?

Runs a live query against the second-largest general web search engine and returns the whole results page as structured data. As with the primary engine, the response is not limited to standard web results: answer boxes, featured snippets, related questions, local packs, image and video blocks, shopping carousels, and AI overviews all come back typed and ranked. This is the natural way to measure how visibility for the same query differs between the two major engines.

### What does Bing organic results take?

keyword is required; the rest of the fields are optional. Send them in the input object of a POST to /v1/run.

### What are the limits on Bing organic results?

The catalog lists an execution timeout of 3 min. A request can return READY or RUNNING before completion; poll GET /v1/runs/{runId} with the same API key until it reaches a terminal status. An HTTP timeout does not prove the generation stopped.

### How do I retry safely and check the final charge?

Save a unique Idempotency-Key for each job. After a network error or HTML timeout, resend the identical POST body with the same key and API key to recover the existing run, then poll its runId. A new key can start another billable generation. An HTTP error or timeout does not establish the run outcome or final charge. Pending runs can still settle; check the terminal price.amount and billing state, and retain the runId for reconciliation. Do not automatically create a new job after a terminal failure.
