ChangelogNew

See how much of your page ChatGPT reads

API
GEO Score with the POST /v1/geo-score chip and the result for an OLIVE YOUNG sunscreen page: GEO Score 29, ChatGPT opening the page 29, with AI Rendering 100, and the two issues that cost the most points

Send a page URL to GEO Score and get the share of the page ChatGPT search keeps, what ChatGPT receives when it opens the page, and the reason and fix for every piece it misses.

What you get

  • POST /v1/geo-score: one task scores one page. Send its url and the reader’s country, US or KR.
  • score: the share of what a person reads on the page, the text inside its images included, that ChatGPT search keeps, from 0 to 100. direct gives the same share for what ChatGPT receives when it opens the page itself.
  • reading.items: every piece of the page, where it sits and why ChatGPT search misses it: blocked, javascript_only, structured_data_only or image_only.
  • analysis: the issues ranked by the points they cost, each with its cause and fix, and potential, the score once the confirmed issues are fixed.
  • markdown and screenshot: the page as a person sees it, with each missing piece marked where it sits. rendering gives the share a copy rendered for AI agents would carry.
  • In the dashboard, the Playground’s GEO Score tab shows the Human view beside the Bot view.

How it works

GEO Score reads robots.txt for OAI-SearchBot, ChatGPT-User and GPTBot and fetches the page as each of them and as a browser. A browser in country renders the page, scrolls to the end and reads the text in its large images. Lines about the page’s own subject become pieces; menus, footers, other products, reviews, buttons and ads stay out of the score.

The ChatGPT search copy is the page rendered as OAI-SearchBot from a US address: the text of the HTML and what scripts draw from it, without the text inside images or content the page loads after it opens. direct reads the HTML ChatGPT-User receives the way ChatGPT’s reader does, and production ChatGPT is asked twice to open the page to see whether it can.

Code places every piece, so a page that has not changed gets the same score. Of 15 pages scored three times each, 10 moved 3 points or less.

Where it helps

  • Score a product or landing page before launch and fix what ChatGPT cannot see, such as prices loaded by script or specs written inside images.
  • Score a competitor’s page that ChatGPT cites for your category beside your own page.
  • Hand the analysis fixes to your web team and score the page again once the change is live.
  • Check whether your site turns ChatGPT away: access.verdict and blockedBy show who keeps it from opening the page.

Send a request

Send the request with your API key in the Authorization header.

curl -X POST https://api.querying.ai/v1/geo-score \
  -H "Authorization: Bearer $QUERYING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://global.oliveyoung.com/product/detail?prdtNo=GA240322874",
    "country": "US"
  }'

Request fields

urlstringRequired
The page to score: an http or https URL on a public host and the default port, up to 2,048 characters.
countrystring
Where the reader is: US (default) or KR. The page is opened from an address in that country, in its language and time zone.
webhook.urlstring
An HTTPS address on your server. The finished task is posted there the moment it completes.
idempotencyKeystring
Your own ID for the request. Each key creates one task per account, so a retried send stays a single task.

Response

A finished task looks like this, trimmed for length.

JSON
{
  "success": true,
  "task": {
    "id": "bcb7e1a2-26eb-422f-9f60-31a5e39ee400",
    "taskType": "GEO_SCORE",
    "status": "COMPLETED",
    "createdAt": "2026-10-23T00:02:42.974Z"
  },
  "credits": { "creditsToCharge": 60, "creditsCharged": 60 },
  "response": {
    "url": "https://global.oliveyoung.com/product/detail?prdtNo=GA240322874",
    "pageType": "product",
    "score": 29,
    "direct": { "score": 29, "read": 16 },
    "rendering": { "score": 100, "read": 55 },
    "access": {
      "verdict": "open",
      "chatgpt": { "opened": true, "lines": 819 }
    },
    "reading": {
      "facts": 55,
      "read": 16,
      "locations": { "html": 16, "rendered_only": 13, "image": 26 },
      "items": [
        {
          "label": "COSRX Vitamin E Vitalizing Sunscreen SPF 50+",
          "where": "html",
          "status": "read"
        },
        {
          "label": "US$16.80",
          "where": "rendered_only",
          "status": "missing",
          "reason": "javascript_only"
        },
        {
          "label": "Key Ingredients",
          "where": "image",
          "status": "missing",
          "reason": "image_only"
        },
        "…"
      ]
    },
    "analysis": {
      "summary": "ChatGPT search keeps 16 of 55 facts of the page. The biggest issue: 26 facts are written only inside an image, among them Strong and effective sun protection; Key Ingredients; Tocopherol (Vitamin E) (47 points). Fixing the confirmed issues could raise the score to about 100.",
      "potential": 100,
      "issues": [
        {
          "code": "image_only",
          "points": 47,
          "title": "26 facts are written only inside an image",
          "fix": "Write this content as text in the page's HTML, next to the image or in place of it …"
        },
        {
          "code": "javascript_only",
          "points": 24,
          "title": "13 facts are loaded only after the page opens",
          "…": "…"
        }
      ]
    },
    "images": { "read": 10, "reused": 0, "unread": 0 },
    "markdown": "…",
    "screenshot": { "status": "ok", "url": "…", "expiresAt": "…" }
  }
}
task.statusstring
QUEUED, PROCESSING, then COMPLETED with the answer or FAILED with error.
credits.creditsChargedinteger
Credits charged for the finished task. A failed task charges 0.
response.scorenumber
The share of what a person reads on the page, the text inside its images included, that ChatGPT search keeps in its copy of the page, from 0 to 100. It is 0 when robots.txt or the site keeps ChatGPT search’s crawler out.
response.directobject
What ChatGPT receives when it opens the page itself, as when someone gives it the URL: its score and the count of pieces it read. The score is 0 when ChatGPT could not open the page.
response.renderingobject
The share of pieces a copy of the page rendered for AI agents holds in its text: the HTML a browser drew, without scripts, with each image’s text in its alt text.
response.reading.itemsarray
One entry per piece of the page: its label, where it sits (html, rendered_only, image and more), status read or missing, and the reason ChatGPT search misses it: blocked, javascript_only, structured_data_only or image_only.
response.analysisobject
summary, potential (the score once the confirmed issues are fixed) and issues, ranked by the points each costs, each with its cause (detail), its fix and the pieces it affects. The text is in English.

Receive the result

The request returns the task right away with status QUEUED. Poll GET /v1/async/task/{id} until status is COMPLETED or FAILED, or add webhook.url and the finished task arrives at your server with the same task, credits and response. Results stay available for 24 hours after a task finishes.

curl https://api.querying.ai/v1/async/task/$TASK_ID \
  -H "Authorization: Bearer $QUERYING_API_KEY"

Errors

VALIDATION_ERRORHTTP 422
url is missing, is not http or https, or names a private host or port. details names the field.
USE_DEDICATED_ENDPOINTHTTP 400
GEO_SCORE was sent to /v1/async/task. Send it to /v1/geo-score.
REGION_UNSUPPORTEDHTTP 422
country is not US or KR.
MISSING_API_KEYHTTP 401
The Authorization header is missing, or its key is unknown, expired or revoked.
INSUFFICIENT_CREDITSHTTP 402
The balance is below 70 credits, the most a page costs. Add credits or upgrade the plan, then send again.

Pricing

A completed score uses 10 credits for the page and 5 for each image whose text is read, at most 12 images. An image your account read in the last 90 days costs 2, and an image that could not be read is free. Submitting holds 70 credits, the most a page costs, and completion charges what the task used.

A failed task is not charged. When no browser can show the page, the task fails with PAGE_UNAVAILABLE and the reason.

More updates

Stay in the loop

Get new product updates in your inbox.

RSS feed