Structured data

Popular page types as typed JSON: Reddit posts, search and comments, and Bing and DuckDuckGo results.

Embed
Preview of the card
<a href="https://scrapelyserp.com/reference/structured"><img src="https://scrapelyserp.com/reference/_api/public/orgs/affc5b0f-d3c2-423a-8143-9d10db5736ae/spaces/e4cbe065-c1c2-4572-b134-0292dedd9c39/pages/aa4b765d-1200-445c-865c-b40d9dd95713/social-card.svg?v=3e7ae33eec8b" alt="Structured data" width="600" height="315"></a>

Popular page types as typed JSON: Reddit posts, search and comments, and Bing and DuckDuckGo results.

Endpoints

Method

Path

Does

GET

/v1/structured

List structured endpoints

GET

/v1/structured/amazon/search

Amazon search

GET

/v1/structured/amazon/image-search

Amazon image search

GET

/v1/structured/amazon/deals

Amazon deals

GET

/v1/structured/walmart/search

Walmart search

GET

/v1/structured/target/search

Target search

GET

/v1/structured/bestbuy/search

Best Buy search

GET

/v1/structured/petsmart/search

PetSmart search

GET

/v1/structured/samsclub/search

Sam's Club search

GET

/v1/structured/walgreens/search

Walgreens search

GET

/v1/structured/cvs/search

CVS search

GET

/v1/structured/bjs/search

BJ's search

GET

/v1/structured/stockx/search

StockX search

GET

/v1/structured/goat/search

GOAT search

GET

/v1/structured/tcgplayer/search

TCGplayer search

GET

/v1/structured/staples/search

Staples search

GET

/v1/structured/kohls/search

Kohl's search

GET

/v1/structured/officedepot/search

Office Depot search

GET

/v1/structured/ikea/search

IKEA search

GET

/v1/structured/poshmark/search

Poshmark search

GET

/v1/structured/gamestop/search

GameStop search

GET

/v1/structured/dicks/search

Dick's search

GET

/v1/structured/grailed/search

Grailed search

GET

/v1/structured/macys/search

Macy's search

GET

/v1/structured/sephora/search

Sephora search

GET

/v1/structured/newegg/search

Newegg category listing

GET

/v1/structured/ulta/search

Ulta Beauty search

GET

/v1/structured/whatnot/search

Whatnot search

GET

/v1/structured/kroger/search

Kroger search

GET

/v1/structured/homedepot/search

Home Depot search

GET

/v1/structured/wayfair/search

Wayfair search

GET

/v1/structured/shopify/catalog

Shopify store catalog

GET

/v1/structured/reddit/posts

Reddit posts

GET

/v1/structured/reddit/search

Reddit search

GET

/v1/structured/reddit/comments

Reddit comments

GET

/v1/structured/bing/search

Bing search

GET

/v1/structured/duckduckgo/search

DuckDuckGo search

GET

/v1/structured/gemini/answer

Gemini answer

GET

/v1/structured/chatgpt/answer

ChatGPT answer

GET

/v1/structured/bluesky/search

Bluesky search

GET

/v1/structured/bluesky/posts

Bluesky posts

GET

/v1/structured/mastodon/hashtag

Mastodon hashtag

GET

/v1/structured/lemmy/search

Lemmy search

GET

/v1/structured/lemmy/posts

Lemmy community posts

GET

/v1/structured/discourse/search

Discourse search

GET

/v1/structured/discourse/topic

Discourse topic

GET

/v1/structured/tumblr/tagged

Tumblr tagged posts

GET

/v1/structured/tumblr/search

Tumblr search

GET

/v1/structured/hackernews/search

Hacker News search

GET

/v1/structured/hackernews/items

Hacker News items

GET

/v1/structured/devto/articles

Dev.to articles

GET

/v1/structured/devto/article

Dev.to article

GET

/v1/structured/wikipedia/search

Wikipedia search

GET

/v1/structured/wikipedia/pages

Wikipedia pages

GET

/v1/structured/reverb/search

Reverb search

GET

/v1/structured/github/search

GitHub search

GET

/v1/structured/github/lookup

GitHub lookup

GET

/v1/structured/stackexchange/search

Stack Exchange search

GET

/v1/structured/stackexchange/questions

Stack Exchange questions

How it works, when to use what, and what it costs: Reddit and web search. Base URL, authentication and errors: Overview.

GET /v1/structured

List structured endpoints.

Every structured endpoint with its parameters and status (live or coming_soon).

Request

curl "https://api.scrapelyserp.com/v1/structured" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY"

Response

{
  "object": "list",
  "data": [
    {
      "id": "reddit/posts",
      "site": "reddit",
      "name": "Reddit posts",
      "description": "The posts of a subreddit, newest or top first.",
      "status": "live",
      "coming_soon": false,
      "url": "https://api.scrapelyserp.com/api/v1/structured/reddit/posts",
      "params": [
        {
          "name": "subreddit",
          "type": "string",
          "required": true,
          "default": null,
          "values": null,
          "description": "The subreddit, with or without r/."
        }
      ],
      "example": {
        "subreddit": "webscraping",
        "sort": "new"
      }
    }
  ]
}

Responses

Status

Meaning

200

Every structured endpoint with its parameters.

401

UNAUTHORIZED: missing, unknown or revoked key.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

Response fields

Field

Type

Description

object

"list"

—

data

object[]

—

Amazon search.

Amazon search results for a query, in Amazon's order: ASIN, title, price and list price, rating, review count, image and whether the placement is sponsored. 16 to 60 per page (Amazon picks the layout for each query); send next_page back as page for more, up to page 20. sort is best_match, best_selling, price_low, price_high, rating or newest. Sponsored placements are included and marked sponsored: true. price is the price the result shows (null when it shows none) and list_price the struck-through list or typical price when there is one. brand and in_stock are always null: search does not carry them, ask POST /v1/products. Each id (and asin) is what POST /v1/products takes. A keyword that matches nothing is an empty list (total_results 0), and so is a page past the last one; an answer we cannot read is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list. Amazon US.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–20 (Amazon shows at most 20). Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, price_low, price_high, rating, newest. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/amazon/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=wireless earbuds"

Response

{
  "endpoint": "amazon/search",
  "url": "https://www.amazon.com/s?k=wireless%20earbuds",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "wireless earbuds",
    "page": 1,
    "total_results": 29095,
    "next_page": 2,
    "results": [
      {
        "position": 3,
        "id": "B0BQPNMXQV",
        "asin": "B0BQPNMXQV",
        "title": "JBL Vibe Beam - True Wireless Earbuds - Black",
        "url": "https://www.amazon.com/dp/B0BQPNMXQV",
        "brand": null,
        "image": "https://m.media-amazon.com/images/I/41+1Csr1pSL._AC_UY218_.jpg",
        "price": {
          "amount": 29.95,
          "currency": "USD"
        },
        "list_price": {
          "amount": 49.95,
          "currency": "USD"
        },
        "rating": 4.2,
        "reviews_count": 41401,
        "in_stock": null,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The amazon search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Amazon image search.

Amazon products that look like a photo: the objects found in it, ranked ASIN matches with a score each, and title, price, list price, rating, reviews, stock, brand and variations for the top matches. Send an image URL, up to 10 image URLs, or the image itself in base64 with POST. JPEG and PNG.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

image_url

string

—

A public http or https URL of a JPEG or PNG photo.

image_urls

string

—

Up to 10 image URLs: a JSON array, or comma-separated. Each is answered on its own, in the order sent.

image_base64

string

—

POST only: the image itself, base64 (a data:image/jpeg;base64, prefix is fine). JPEG or PNG, up to 3.5 MB.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/amazon/image-search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "image_url=https://m.media-amazon.com/images/I/61PQSiTkywL.jpg"

Response

{
  "endpoint": "amazon/image-search",
  "url": "https://www.amazon.com/",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "results": [
      {
        "image_url": "https://m.media-amazon.com/images/I/61PQSiTkywL.jpg",
        "status": "ok",
        "objects": [
          {
            "label": "footwear",
            "category": "shoes",
            "score": 0.9655,
            "box": {
              "x": 7,
              "y": 158,
              "width": 787,
              "height": 369,
              "image_width": 800,
              "image_height": 571
            }
          }
        ],
        "matches": [
          {
            "rank": 1,
            "asin": "B08Q9SDCFJ",
            "score": 0.9158,
            "kind": "visual",
            "object": 0
          },
          {
            "rank": 2,
            "asin": "B08QB1QMJ5",
            "score": 0.8803,
            "kind": "visual",
            "object": 0
          }
        ],
        "products": [
          {
            "asin": "B08Q9SDCFJ",
            "title": "Nike Women's Dunk Low Sneaker",
            "url": "https://www.amazon.com/dp/B08Q9SDCFJ",
            "brand": "Nike",
            "image": "https://m.media-amazon.com/images/I/61PQSiTkywL.jpg",
            "price": {
              "amount": 99.95,
              "currency": "USD"
            },
            "list_price": {
              "amount": 120,
              "currency": "USD"
            },
            "rating": 4.6,
            "reviews_count": 3720,
            "availability": "in_stock",
            "in_stock": true,
            "variations": ["B0BKR4NWW6", "B0DC6Z3CXX"],
            "colors": []
          }
        ],
        "queries": []
      }
    ]
  }
}

Responses

Status

Meaning

200

The amazon image search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.results

object[]

One per image, in the order sent.

GET /v1/structured/amazon/deals

Amazon deals.

Today's Amazon deals, in Amazon's order: ASIN, title, deal price and list price, percent off, deal type and badge, end time for lightning deals, rating, reviews, brand and variation count. Filter by department, brand, rating or Prime Exclusive; up to 100 deals per page.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

department

string

—

Only deals in one department: our slug (e.g. electronics) or Amazon's name (Home & Kitchen). filters.departments lists them with their deals.

brand

string

—

Only deals of one brand: its id from filters.brands (with include_filters=true), e.g. 323125 (Amazon).

min_rating

string

—

4: only products rated 4 stars and up (the one rating filter Amazon offers here). One of: 4.

access

string

—

prime_exclusive: only deals for Prime members. One of: prime_exclusive.

page

integer

—

Page, 1–100. The list runs to about 500 deals; next_page is null on the last page. Default 1.

limit

integer

—

Deals per page, 1–100. Pages are limit apart: keep it the same while paging. Default 60.

include_filters

boolean

—

Also return filters: the departments, brands (the top 20), ratings and access programs of the deals that match, with the ids these parameters take. Default false.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/amazon/deals" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d department=electronics \
  -d limit=20

Response

{
  "endpoint": "amazon/deals",
  "url": "https://www.amazon.com/deals",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "page": 1,
    "limit": 2,
    "next_page": 2,
    "deals": [
      {
        "position": 1,
        "asin": "B0F7Z4QZTT",
        "title": "Amazon Fire TV Stick 4K Plus with AI-powered Fire TV Search, Wi-Fi 6",
        "url": "https://www.amazon.com/dp/B0F7Z4QZTT",
        "image": "https://m.media-amazon.com/images/I/51WtNy0OxLL.jpg",
        "brand": "Amazon",
        "brand_id": "323125",
        "price": {
          "amount": 39.99,
          "currency": "USD"
        },
        "list_price": {
          "amount": 69.99,
          "currency": "USD"
        },
        "percent_off": 43,
        "deal_type": "best_deal",
        "badge": "Limited time deal",
        "deal_state": "available",
        "ends_at": null,
        "claimed_percent": null,
        "rating": 4.6,
        "reviews_count": 116169,
        "variations": 1
      },
      {
        "position": 2,
        "asin": "B0C1NQZDYH",
        "title": "BEDLORE Waterproof Mattress Protector, King Size Mattress Pad",
        "url": "https://www.amazon.com/dp/B0C1NQZDYH",
        "image": "https://m.media-amazon.com/images/I/81X+MBrUg+L.jpg",
        "brand": "BEDLORE",
        "brand_id": "4742140",
        "price": {
          "amount": 26.38,
          "currency": "USD"
        },
        "list_price": {
          "amount": 32.99,
          "currency": "USD"
        },
        "percent_off": 20,
        "deal_type": "lightning_deal",
        "badge": "Ends in",
        "deal_state": "available",
        "ends_at": "2026-11-06T05:50:00.000Z",
        "claimed_percent": 32,
        "rating": 4.6,
        "reviews_count": 29101,
        "variations": 61
      }
    ]
  }
}

Responses

Status

Meaning

200

The amazon deals as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.page

integer

—

data.limit

integer

—

data.next_page

integer or null

Send as page for the next page; null on the last.

data.deals

object[]

In Amazon's order. Empty past the end of the list.

data.filters

object

With include_filters=true: the choices for the deals that match, with the ids the parameters take.

Walmart search.

Walmart search results for a query, in the site's order: item id, title, brand, price and list price, rating, review count, stock and image. 25 per page; send next_page back as page for more. Each id is what POST /v1/products takes for Walmart.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, price_low, price_high. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/walmart/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=air fryer"

Response

{
  "endpoint": "walmart/search",
  "url": "https://www.walmart.com/search?q=air%20fryer",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "air fryer",
    "page": 1,
    "total_results": 2498,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "16101019328",
        "title": "Beautiful by Drew Barrymore 6 qt Air Fryer with TurboCrisp Technology, White Icing",
        "url": "https://www.walmart.com/ip/16101019328",
        "brand": "Beautiful",
        "image": null,
        "price": {
          "amount": 59,
          "currency": "USD"
        },
        "list_price": {
          "amount": 69,
          "currency": "USD"
        },
        "rating": 4.6,
        "reviews_count": 20544,
        "in_stock": true,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The walmart search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Target search.

Target search results for a query, in the site's order: TCIN, title, brand, price and regular price, rating, review count and image. 24 per page; send next_page back as page for more. Each id is what POST /v1/products takes for Target.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, price_low, price_high, rating, newest. Default best_match.

zip

string

—

A 5-digit US ZIP code. Results reflect that area (local prices, stock and nearby results). Unknown ZIP codes are a free 400.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/target/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=air fryer"

Response

{
  "endpoint": "target/search",
  "url": "https://www.target.com/s?searchTerm=air%20fryer",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "air fryer",
    "page": 1,
    "total_results": 272,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "89110863",
        "title": "Gourmia 6qt Digital Window Air Fryer with 12 Presets & Guided Cooking Black",
        "url": "https://www.target.com/p/-/A-89110863",
        "brand": "Gourmia",
        "image": null,
        "price": {
          "amount": 44.99,
          "currency": "USD"
        },
        "list_price": {
          "amount": 69.99,
          "currency": "USD"
        },
        "rating": 4.07,
        "reviews_count": 2309,
        "in_stock": null,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The target search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Best Buy search.

Best Buy search results for a query, in the site's order: SKU, title, brand, price and regular price, rating, review count and image. 50 per page; send next_page back as page for more. Each id is what POST /v1/products takes for Best Buy.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, price_low, price_high, rating, newest, discount. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/bestbuy/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=air fryer"

Response

{
  "endpoint": "bestbuy/search",
  "url": "https://www.bestbuy.com/site/searchpage.jsp?st=air%20fryer",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "air fryer",
    "page": 1,
    "total_results": 66,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "6583884",
        "title": "bella PRO - SmartCrisp 8-qt. Touchscreen Air Fryer - Stainless Steel",
        "url": "https://www.bestbuy.com/site/6583884.p?skuId=6583884",
        "brand": "bella PRO",
        "image": null,
        "price": {
          "amount": 59.99,
          "currency": "USD"
        },
        "list_price": {
          "amount": 129.99,
          "currency": "USD"
        },
        "rating": 4.6,
        "reviews_count": 1840,
        "in_stock": null,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The best buy search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

PetSmart search.

PetSmart search results for a query, in the site's order: product id, title, brand, lowest and highest price, rating, review count, stock and image. 40 per page; send next_page back as page for more. Each id is what POST /v1/products takes for PetSmart.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, price_low, price_high, newest, rating. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/petsmart/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=dog food"

Response

{
  "endpoint": "petsmart/search",
  "url": "https://www.petsmart.com/search?q=dog%20food",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "dog food",
    "page": 1,
    "total_results": 4034,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "36648",
        "title": "Purina Pro Plan Sensitive Skin and Stomach Dry Dog Food Adult Salmon & Rice Formula Digestive Health",
        "url": "https://www.petsmart.com/dog/food/dry-food/purina-pro-plan-sensitive-skin-and-stomach-dry-dog-food-adult-salmon-and-rice-formula-digestive-health-36648.html",
        "brand": "Purina Pro Plan",
        "image": null,
        "price": {
          "amount": 20.68,
          "currency": "USD"
        },
        "price_max": {
          "amount": 94.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.5,
        "reviews_count": 9248,
        "in_stock": true,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The petsmart search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Sam's Club search.

Sam's Club search results for a query, in the site's order: item id, title, brand (often null), price and regular price, rating, review count, stock and image. about 45 per page; send next_page back as page for more. Each id is what POST /v1/products takes for Sam's Club. Sponsored placements are left out. Sam's Club often refuses a request: a call can answer 502 TARGET_FAILED (not charged), so retry it, and a keyword that lands on a category page instead of results is a failure, not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, price_low, price_high. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/samsclub/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=vitamins

Response

{
  "endpoint": "samsclub/search",
  "url": "https://www.samsclub.com/s/vitamins",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "vitamins",
    "page": 1,
    "total_results": 256,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "13899862238",
        "title": "Member's Mark Advanced Women's 50+ Multivitamin Tablets, 275 ct.",
        "url": "https://www.samsclub.com/ip/Member-s-Mark-Advanced-Women-s-50-Multivitamin-Tablets-275-ct/13899862238",
        "brand": null,
        "image": null,
        "price": {
          "amount": 13.34,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.5,
        "reviews_count": 859,
        "in_stock": true,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The sam's club search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Walgreens search.

Walgreens search results for a query, in the site's order: product id, title, brand, price and regular price, rating, review count, stock and image. rating is in half stars (4.0, 4.5), not exact. Up to 72 per call, one page only (no page or sort); total_results counts all matches. in_stock is null when Walgreens does not say. Each id is what POST /v1/products takes for Walgreens. A keyword that lands on a service page instead of products (such as 'prescription') is a failure, not an empty list, and so is a block: a call can answer 502 TARGET_FAILED (not charged), so retry it. Prescription items are never returned.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/walgreens/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=shampoo

Response

{
  "endpoint": "walgreens/search",
  "url": "https://www.walgreens.com/q/shampoo",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "shampoo",
    "page": 1,
    "total_results": 526,
    "next_page": null,
    "results": [
      {
        "position": 1,
        "id": "300452904",
        "title": "Walgreens Shiny & Smooth Shampoo",
        "url": "https://www.walgreens.com/store/c/walgreens-shiny-%26-smooth-shampoo/ID=300452904-product",
        "brand": "Walgreens",
        "image": null,
        "price": {
          "amount": 3.74,
          "currency": "USD"
        },
        "list_price": {
          "amount": 4.99,
          "currency": "USD"
        },
        "rating": 4,
        "reviews_count": 90,
        "in_stock": true
      }
    ]
  }
}

Responses

Status

Meaning

200

The walgreens search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

CVS search.

CVS search results for a query, in the site's order: product id, title, brand, price (the lowest, with price_max when the product has variants at different prices) and regular price, rating, review count and image. 40 per page; send next_page back as page for more. sort is best_match or price_low. in_stock is always null: search does not report availability. Sponsored placements and prescription items are left out. Each id is what POST /v1/products takes for CVS. CVS often refuses a request: a call can answer 502 TARGET_FAILED (not charged), so retry it, and an answer that is not clearly a list of products or a count of zero is a failure, not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, price_low. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/cvs/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=shampoo

Response

{
  "endpoint": "cvs/search",
  "url": "https://www.cvs.com/search?searchTerm=shampoo",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "shampoo",
    "page": 1,
    "total_results": 497,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "949346",
        "title": "Carol's Daughter Lisa's Kitchen Scalp Detox Cleansing Nectar, 8 OZ",
        "url": "https://www.cvs.com/shop/carol-s-daughter-lisa-s-kitchen-scalp-detox-cleansing-nectar-8-oz-prodid-949346",
        "brand": "Carol's Daughter",
        "image": null,
        "price": {
          "amount": 12.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.74,
        "reviews_count": 153,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The cvs search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

BJ's search.

BJ's search results for a query, in the site's order: item number, title, brand (null when BJ's gives none), price_range (low and high), rating, review count and image. 100 per page; send next_page back as page for more. sort is best_match, rating or newest. price and list_price are always null: BJ's data gives a price range, not the price at a given club, and the current club price is not available. in_stock is always null: search does not report availability. Each id is what POST /v1/products takes for BJ's. A keyword that matches nothing still returns BJ's nearest items, and an answer that is not clearly a list of products or a count of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list. Prescription items are never returned.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, rating, newest. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/bjs/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=coffee

Response

{
  "endpoint": "bjs/search",
  "url": "https://www.bjs.com/search/coffee",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "coffee",
    "page": 1,
    "total_results": 219,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "328157",
        "title": "Maxwell House Medium Roast Original Ground Coffee, 43.1 oz.",
        "url": "https://www.bjs.com/product/maxwell-house-medium-roast-original-ground-coffee-431-oz/3000000000005070289/",
        "brand": null,
        "image": "https://bjs.scene7.com/is/image/bjs/328157",
        "price": null,
        "list_price": null,
        "price_range": {
          "min": {
            "amount": 15.29,
            "currency": "USD"
          },
          "max": {
            "amount": 22.99,
            "currency": "USD"
          }
        },
        "rating": 5,
        "reviews_count": 1344,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The bj's search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

StockX search.

StockX search results for a query, in the site's order: slug, title, brand, lowest ask (as price), whether anything is on sale, and image. 40 per page; send next_page back as page for more. Each id is what POST /v1/products takes for StockX.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, trending, best_selling, price_low, newest. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/stockx/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=dunk low"

Response

{
  "endpoint": "stockx/search",
  "url": "https://stockx.com/search?s=dunk%20low",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "dunk low",
    "page": 1,
    "total_results": 1000,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "nike-dunk-low-retro-white-black-2021",
        "title": "Nike Dunk Low Retro White Black Panda",
        "url": "https://stockx.com/nike-dunk-low-retro-white-black-2021",
        "brand": "Nike",
        "image": null,
        "price": {
          "amount": 59,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": true,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The stockx search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

GOAT search.

GOAT search results for a query, in the site's order: slug, title, brand, lowest price, retail price, stock and image. 24 per page; send next_page back as page for more. Each id is what POST /v1/products takes for GOAT.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, newest, price_low, price_high, trending, discount. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/goat/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=dunk low"

Response

{
  "endpoint": "goat/search",
  "url": "https://www.goat.com/search?query=dunk%20low",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "dunk low",
    "page": 1,
    "total_results": 3239,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "dunk-low-black-white-dd1391-100",
        "title": "Nike Dunk Low 'Black White'",
        "url": "https://www.goat.com/sneakers/dunk-low-black-white-dd1391-100",
        "brand": "Nike",
        "image": null,
        "price": {
          "amount": 59,
          "currency": "USD"
        },
        "list_price": {
          "amount": 100,
          "currency": "USD"
        },
        "rating": null,
        "reviews_count": null,
        "in_stock": true,
        "sponsored": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The goat search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

TCGplayer search.

TCGplayer search results for a query, in the site's order: product id, title, market price (as price), whether any listing exists, and image. 50 per page; send next_page back as page for more. sort is best_match, best_selling, price_low, price_high (both on the market price), listing_low (cheapest listing first), newest or name; product_line narrows to one game (pokemon, yugioh, star-wars-unlimited). price is TCGplayer's market price, a figure from recent sales for the product, and null when it has none; list_price, rating and reviews_count are always null. in_stock is true when at least one listing exists. Each id is what POST /v1/products takes for TCGplayer. An answer that is not clearly a list of products or a count of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, price_low, price_high, listing_low, newest, name. Default best_match.

product_line

string

—

Only this game or product line, by its lower-case name (pokemon, yugioh, magic, star-wars-unlimited). A name that matches nothing is an empty list.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/tcgplayer/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=charizard

Response

{
  "endpoint": "tcgplayer/search",
  "url": "https://www.tcgplayer.com/search/all/product?q=charizard",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "charizard",
    "page": 1,
    "total_results": 382,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "662182",
        "title": "Mega Charizard X ex - 013/094",
        "url": "https://www.tcgplayer.com/product/662182/pokemon-me02-phantasmal-flames-mega-charizard-x-ex-013-094",
        "brand": null,
        "image": "https://product-images.tcgplayer.com/fit-in/437x608/662182.jpg",
        "price": {
          "amount": 3.55,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": true
      }
    ]
  }
}

Responses

Status

Meaning

200

The tcgplayer search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Staples search.

Staples search results for a query, in the site's order: item id, title, brand, price (for one unit), link and image. 100 per page; send next_page back as page for more, up to page 100 (10,000 results). sort is best_match, price_low or price_high. list_price, rating, reviews_count and in_stock are always null: search does not carry them, ask POST /v1/products. A set of options (an id starting SS) has price null. Each id is what POST /v1/products takes for Staples. A keyword that matches nothing still returns Staples' nearest item (one result), and an answer that is not clearly a list of products or a count of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, price_low, price_high. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/staples/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=copy paper"

Response

{
  "endpoint": "staples/search",
  "url": "https://www.staples.com/copy%20paper/directory_copy%20paper",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "copy paper",
    "page": 1,
    "total_results": 11201,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "122374",
        "title": "Hammermill Copy Plus 8.5\" x 11\" Copy Paper, 20 lbs., 92 Brightness, 5000 Sheets/Carton (105007)",
        "url": "https://www.staples.com/product_122374",
        "brand": "Hammermill",
        "image": "https://www.staples-3p.com/s7/is/image/Staples/0A9DEFAA-5A39-42C6-938F42EAB5C0ACCF",
        "price": {
          "amount": 49.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The staples search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Kohl's search.

Kohl's search results for a query, a category, or both, in the site's order: product id, title, price, regular price, rating, review count, link and image. 120 per page; send next_page back as page for more. sort is best_match, newest, price_low, price_high or rating. category is a Kohl's category value (the CN= part of a Kohl's catalog link, Gender:Mens+Category:Bottoms+Department:Clothing); with a category the query is optional and narrows within it. price is the regular price, or the sale price when marked down; it is never the 20% coupon price Kohl's pages lead with. A product with options at different prices has price null and a price_range (low and high); list_price is the regular price of a product on sale at one price. Sponsored placements are left out. brand is always null and in_stock is always null: Kohl's search carries neither. Each id is what POST /v1/products takes for Kohl's. A keyword that matches nothing still returns Kohl's closest items (33 for a nonsense word), and a category Kohl's does not recognize, a page past the last one, or an answer that is not clearly a list of products or a count of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list. A request with neither query nor category is refused.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

—

The search terms. Required unless category is given.

category

string

—

A Kohl's category value (the CN= part of a catalog link), e.g. Gender:Mens+Category:Bottoms+Department:Clothing. Lists that category; query then narrows it.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, newest, price_low, price_high, rating. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/kohls/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=mens jeans"

Response

{
  "endpoint": "kohls/search",
  "url": "https://www.kohls.com/search.jsp?search=mens%20jeans",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "mens jeans",
    "page": 1,
    "total_results": 2198,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "7431597",
        "title": "Sonoma Goods For Life Hygro Performance Bath Towel, Bath Sheet, Hand Towel or Washcloth",
        "url": "https://www.kohls.com/product/prd-7431597/sonoma-goods-for-life-hygro-performance-bath-towel-bath-sheet-hand-towel-or-washcloth.jsp",
        "brand": null,
        "image": "https://media.kohlsimg.com/is/image/kohls/7431597_Blush?wid=180&hei=180&op_sharpen=1",
        "price": null,
        "price_range": {
          "min": {
            "amount": 7.99,
            "currency": "USD"
          },
          "max": {
            "amount": 49.99,
            "currency": "USD"
          }
        },
        "list_price": null,
        "rating": 4.4,
        "reviews_count": 14485,
        "in_stock": null
      },
      {
        "position": 2,
        "id": "8363284",
        "title": "Men's Vintage America Straight Fit Denim Jeans",
        "url": "https://www.kohls.com/product/prd-8363284/mens-vintage-america-straight-fit-denim-jeans.jsp",
        "brand": null,
        "image": "https://media.kohlsimg.com/is/image/kohls/8363284_Liberty_Wash?wid=180&hei=180&op_sharpen=1",
        "price": {
          "amount": 26.4,
          "currency": "USD"
        },
        "price_range": null,
        "list_price": {
          "amount": 44,
          "currency": "USD"
        },
        "rating": 5,
        "reviews_count": 5,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The kohl's search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Office Depot search.

Office Depot search results for a query, in the site's order: sku, title, brand, price (for one unit), rating, review count, link and image. 24 per page; send next_page back as page for more. sort is best_match, price_low, price_high or rating (Office Depot's Customer Rating order, which favours products with many good reviews over a high average). list_price and in_stock are always null: Office Depot's search results show a wrong list price and a wrong stock status, so ask POST /v1/products for the skus you want. rating and reviews_count are null with no reviews. Sponsored placements are left out. Each id is what POST /v1/products takes for Office Depot. A keyword that matches nothing still returns 200 of Office Depot's products (24 a page, total_results exactly 200) and nothing in the answer marks it: a real search reports its true total (84, 487…), so a total_results of 200 whose titles do not contain your words means no match. An empty list means Office Depot says there are no matches; any other unclear answer is a failure (502 TARGET_FAILED, not charged, retry it).

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, price_low, price_high, rating. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/officedepot/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=printer paper"

Response

{
  "endpoint": "officedepot/search",
  "url": "https://www.officedepot.com/a/search/?q=printer%20paper",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "printer paper",
    "page": 1,
    "total_results": 487,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "301742",
        "title": "JAM Paper® Color Multi-Use Printer & Copy Paper, Brown Kraft, Letter (8.5\" x 11\"), 50 Sheets Per Pack, 28 Lb",
        "url": "https://www.officedepot.com/a/products/301742/JAM-Paper-Color-Multi-Use-Printer/",
        "brand": "JAM Paper",
        "image": "https://media.officedepot.com/images/t_large%2Cf_auto/products/301742/1.jpg",
        "price": {
          "amount": 29.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.67,
        "reviews_count": 3,
        "in_stock": null
      },
      {
        "position": 2,
        "id": "196517",
        "title": "Boise® X-9® Multi-Use Printer & Copy Paper, 10 Reams, White, Letter (8.5\" x 11\"), 5000 Sheets Per Case, 20 Lb, 92 Brightness",
        "url": "https://www.officedepot.com/a/products/196517/Boise-X-9-Multi-Use-Printer/",
        "brand": "BOISE",
        "image": "https://media.officedepot.com/images/t_large%2Cf_auto/products/196517/1.jpg",
        "price": {
          "amount": 48.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.68,
        "reviews_count": 20060,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The office depot search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

IKEA search.

IKEA search results for a query or a category, in the site's order: item number, title, price, regular price, rating, review count, link and image. 100 per page; send next_page back as page for more. sort is best_match, price_low, price_high, newest or rating. category is an IKEA category key (fu003 is sofas & sectionals); with a category the query is optional and narrows within it. price is IKEA's public price. A product that shows an IKEA Family (member) price has that member price in POST /v1/products, never here; list_price is the earlier or regular price of a marked-down product. brand is always null and in_stock is always null: search carries neither (ask POST /v1/products for online availability). Each id is what POST /v1/products takes for IKEA. A keyword that matches nothing returns zero results (200, total_results 0). A category key IKEA does not know, a page past the last one, or an answer that is not clearly a list of products or a count of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list. A request with neither query nor category is refused.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

—

The search terms (at most 150 characters). Required unless category is given.

category

string

—

An IKEA category key, e.g. fu003 (sofas & sectionals). Lists that category; query then narrows it.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, price_low, price_high, newest, rating. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/ikea/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=desk

Response

{
  "endpoint": "ikea/search",
  "url": "https://www.ikea.com/us/en/search/?q=desk",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "desk",
    "page": 1,
    "total_results": 187,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "10514155",
        "title": "IDANÄS Desk, white, 59 7/8x27 1/2 \"",
        "url": "https://www.ikea.com/us/en/p/idanaes-desk-white-10514155/",
        "brand": null,
        "image": "https://www.ikea.com/us/en/images/products/idanaes-desk-white__1159443_pe888489_s5.jpg",
        "price": {
          "amount": 449,
          "currency": "USD"
        },
        "list_price": {
          "amount": 599,
          "currency": "USD"
        },
        "rating": 4.3,
        "reviews_count": 31,
        "in_stock": null
      },
      {
        "position": 2,
        "id": "60609679",
        "title": "GULLABERG L-shaped desk, drop file storage/white, 61x61x29 1/2 \"",
        "url": "https://www.ikea.com/us/en/p/gullaberg-l-shaped-desk-drop-file-storage-white-60609679/",
        "brand": null,
        "image": "https://www.ikea.com/us/en/images/products/gullaberg-l-shaped-desk-drop-file-storage-white__1536835_pe1016995_s5.jpg",
        "price": {
          "amount": 399.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The ikea search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Poshmark search.

Poshmark listings for a query, in the site's order: listing id, title, brand, price, original price, size, condition, stock per size, seller, department, category, likes, link and image. Up to 100 per page for available listings (48 for status=sold); page on with cursor: send next_cursor back as cursor. sort is best_match, newest (just listed), price_low or price_high; condition=new_with_tags and min_price / max_price (dollars) narrow the listings. status is available (the default) or sold; sold listings cost about 5 times as much per listing and take sort and condition but not the price filters. About 5,000 listings are reachable for one query, however many total_results says (it stops at 10,000). price is the seller's listing price, never including fees or shipping; list_price is the original price the seller gave, null when none. rating and reviews_count are always null: listings have none. in_stock is true for an available listing and false for a sold one; poshmark.sizes has the quantity per size. poshmark.condition is new_with_tags or Poshmark's own code, and null when the seller set none. Each id is what POST /v1/products takes for Poshmark. A keyword that matches nothing still returns loose matches (99 for a nonsense word), and an answer that is not clearly a list of listings or a total of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

cursor

string

—

The next_cursor of the previous page, asked with the same status. Poshmark pages by cursor, so there is no page.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, newest, price_low, price_high. Default best_match.

status

string

—

Listings for sale, or sold ones. Sold costs about 5 times as much per listing and returns 48 per page. One of: available, sold. Default available.

condition

string

—

Only listings new with tags. One of: new_with_tags.

min_price

string

—

Lowest listing price, in dollars (a number). Not with status=sold.

max_price

string

—

Highest listing price, in dollars (a number). Not with status=sold.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/poshmark/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=levis jeans"

Response

{
  "endpoint": "poshmark/search",
  "url": "https://poshmark.com/search?query=levis%20jeans",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "levis jeans",
    "page": 1,
    "total_results": 10000,
    "next_page": null,
    "next_cursor": "ENC_eyJtYXhfaWRzIjpbMTAxLDEsMV0sIm1heF9pZF9zY2hlbWUiOiJvcmciLCJwYWdlX251bSI6MiwicGFnZV9ncm91cF9pZCI6IjZhZWNiODc5OGY5ZDNlOGQ3MDdjMmQ5NyJ9",
    "results": [
      {
        "position": 1,
        "id": "6aecb847f09fc893a4990038",
        "title": "NWT signature Levi strauss Gold totally shaping pull on jeans",
        "url": "https://poshmark.com/listing/6aecb847f09fc893a4990038",
        "brand": "signature levi strauss gold",
        "image": "https://di2ponv0v5otw.cloudfront.net/posts/2026/11/05/6aecb847f09fc893a4990038/m_6aecb84cc6a0b3f268778f5a.jpeg",
        "price": {
          "amount": 15,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": true,
        "poshmark": {
          "listingStatus": "available",
          "size": "32",
          "condition": "new_with_tags",
          "sizes": [
            {
              "size": "32",
              "available": 1,
              "sold": 0
            }
          ],
          "seller": "deedeshay0619",
          "department": "Women",
          "category": "Jeans",
          "likes": 0
        }
      }
    ]
  }
}

Responses

Status

Meaning

200

The poshmark search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

GameStop search.

GameStop search results for a query, in the site's order: product id, title, brand (null when GameStop gives none), current price, link and image. 200 per page; send next_page back as page for more. sort is best_match, popular, price_low, price_high or newest. New, pre-owned, digital and refurbished copies are separate products with separate ids and prices; a row shows one of them (the best match), and POST /v1/products lists the others as gamestop.siblings. A pre-owned price can be higher than the new one: it is what GameStop's data says. list_price, rating, reviews_count and in_stock are always null: GameStop's data has no list price and no rating per product, and stock is not reported. Each id is what POST /v1/products takes for GameStop. A keyword that matches no word returns an empty list (total_results 0), not GameStop's fuzzy near-matches, and an answer that is not clearly a list of products or a count of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, popular, price_low, price_high, newest. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/gamestop/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=mario kart"

Response

{
  "endpoint": "gamestop/search",
  "url": "https://www.gamestop.com/search/?q=mario%20kart",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "mario",
    "page": 1,
    "total_results": 512,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "393069",
        "title": "Hallmark Super Mario PVC Figural Mini Ornament Set",
        "url": "https://www.gamestop.com/home/bedroom/decor/products/hallmark-super-mario-pvc-figural-mini-ornament-set/393069.html",
        "brand": "Hallmark",
        "image": "https://media.gamestop.com/i/gamestop/20004908/Hallmark-Super-Mario-PVC-Figural-Mini-Ornament-Set?$thumb$",
        "price": {
          "amount": 9.97,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The gamestop search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Dick's search.

Dick's Sporting Goods search results for a query, in the site's order: sku, title, brand, price, regular price, rating, review count and link. 144 per page; send next_page back as page for more. sort is best_match, price_low or price_high; brand narrows to one brand. Each result is a style shown in one colour, and its id is the sku of that colour and one size: it goes straight into POST /v1/products for Dick's, which returns that sku's price and stock. price is the sku's current price (a sale ends on a date: the price in force now), and list_price the regular price when it is marked down. in_stock is always null: search carries no stock. image is always null. The price orders follow the highest price Dick's has on file for a product, which can be a later non-sale price, so current prices are close to ordered, not exact. A keyword that matches nothing still returns Dick's closest items (2 for a nonsense word we tried) rather than an empty list; a brand that matches nothing is an empty list. A page past the last, and an answer that is not clearly a list of products or a count of zero, is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, price_low, price_high. Default best_match.

brand

string

—

Only this brand, spelled as Dick's does, capital letters included (Nike, Under Armour; nike matches nothing). A name that matches nothing is an empty list.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/dicks/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=running shoes"

Response

{
  "endpoint": "dicks/search",
  "url": "https://www.dickssportinggoods.com/search/SearchDisplay?searchTerm=running%20shoes",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "running shoes",
    "page": 1,
    "total_results": 719,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "28503063",
        "title": "Nike Men's Alphafly 4 Road Racing Shoes",
        "url": "https://www.dickssportinggoods.com/p/nike-mens-alphafly-4-road-racing-shoes-26nikmrunnnklphflyffe/26nikmrunnnklphflyffe",
        "brand": "Nike",
        "image": null,
        "price": {
          "amount": 279.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": null
      },
      {
        "position": 2,
        "id": "26285440",
        "title": "HOKA Women's Clifton 10 Running Shoes",
        "url": "https://www.dickssportinggoods.com/p/hoka-womens-clifton-10-running-shoes-25fhqwclftn10blckftw/25fhqwclftn10blckftw",
        "brand": "Hoka",
        "image": null,
        "price": {
          "amount": 124.97,
          "currency": "USD"
        },
        "list_price": {
          "amount": 154.99,
          "currency": "USD"
        },
        "rating": 4.73,
        "reviews_count": 1970,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The dick's search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Grailed search.

Grailed listings for a query, in the site's order: listing id, title, designers (as brand), asking price, original price, size, condition, department, category, seller and seller rating, likes, listed date, link and image; for a sold listing also the sold price, sold date and shipping paid. Up to 100 per page; send next_page back as page for more. sort is best_match, newest, price_low or price_high; status is available (the default) or sold; department, condition, min_price / max_price (whole dollars, on the asking price), size and designer narrow the listings. Only the first 1,000 listings of a query can be reached (page 1 to 10), however large total_results says: narrow the query with the filters to see more. price is the asking price, on a sold listing too: what a sold listing sold for is grailed.soldPrice (it can be lower, when an offer was accepted), with grailed.soldAt. list_price is the first price in the listing's price-drop history, null when the price never dropped. rating and reviews_count are always null: listings have none (the seller's own rating is grailed.sellerRating). in_stock is true for an available listing and false for a sold one. Each id is what POST /v1/products takes for Grailed. A keyword that matches nothing is an empty list (total_results 0), and an answer that is not clearly a list of listings or a total of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–10 (100 listings each: the first 1,000 of a query). Default 1.

sort

string

—

Result order: best_match is Grailed's own order, newest just listed (most recently sold with status=sold), price_low and price_high by asking price (by sold price with status=sold). One of: best_match, newest, price_low, price_high. Default best_match.

status

string

—

Listings for sale, or sold ones (with their sold price and date). One of: available, sold. Default available.

department

string

—

Only this department. One of: menswear, womenswear.

condition

string

—

Only listings in this condition. One of: new, gently_used, used, worn.

min_price

string

—

Lowest asking price, in whole dollars.

max_price

string

—

Highest asking price, in whole dollars.

size

string

—

Only this size, as Grailed writes it (l, 10, 36, 7.5); capital letters do not matter.

designer

string

—

Only listings by this designer (Nike); capital letters do not matter. Collaborations match each of their designers. A name that matches nothing is an empty list.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/grailed/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=air jordan"

Response

{
  "endpoint": "grailed/search",
  "url": "https://www.grailed.com/shop?query=air%20jordan",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "air jordan",
    "page": 1,
    "total_results": 44619,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "111350058",
        "title": "Fragment Design x Union LA x Air Jordan 1 Retro High OG",
        "url": "https://www.grailed.com/listings/111350058",
        "brand": "Fragment Design × Jordan Brand",
        "image": "https://media-assets.grailed.com/prd/listing/temp/ee3b918ddca746e8b638acc18d2123aa",
        "price": {
          "amount": 170,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": true,
        "grailed": {
          "status": "available",
          "size": "11",
          "condition": "gently_used",
          "category": "footwear",
          "department": "menswear",
          "seller": "616Selects",
          "sellerRating": 5,
          "sellerRatingCount": 13,
          "likes": 8,
          "listedAt": "2026-11-04T21:13:58.022Z",
          "soldPrice": null,
          "soldAt": null,
          "soldShippingPrice": null
        }
      }
    ]
  }
}

Responses

Status

Meaning

200

The grailed search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Macy's search.

Macy's search results for a keyword or a category, in the site's order: product id, title, brand, price, regular price, rating, review count, stock flag, link and image. 60 to 64 per page; send next_page back as page for more. sort is best_match, best_selling, newest, price_low, price_high or rating. category is a Macy's category id (the number after id= in a category link); send query or category, not both. price is the regular price, or the sale price when marked down; it is never a coupon price. A product with options at different prices has price null and a price_range (low and high); list_price is the regular price of a product on sale at one price. in_stock is Macy's own flag on the product, null for a collection of products. Each id is what POST /v1/products takes for Macy's. A keyword that matches nothing still returns Macy's closest items (about 60 on page 1, 97 in total for a nonsense word), and a category Macy's does not recognize, a page past the last one, or an answer that is not clearly a list of products or a count of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list. A request with neither query nor category, or with both, is refused.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

—

The search terms. Required unless category is given; not with category.

category

string

—

A Macy's category id (the number after id= in a category link), e.g. 20635. Lists that category; not with query.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, newest, price_low, price_high, rating. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/macys/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=dress shirt"

Response

{
  "endpoint": "macys/search",
  "url": "https://www.macys.com/shop/featured/dress%20shirt",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "dress shirt",
    "page": 1,
    "total_results": 849,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "18618230",
        "title": "Men's Regular-Fit Heritage Oxford Shirt",
        "url": "https://www.macys.com/shop/product/tommy-hilfiger-mens-regular-fit-heritage-oxford-shirt?ID=18618230",
        "brand": "Tommy Hilfiger",
        "image": null,
        "price": null,
        "price_range": {
          "min": {
            "amount": 28.43,
            "currency": "USD"
          },
          "max": {
            "amount": 89.5,
            "currency": "USD"
          }
        },
        "list_price": null,
        "rating": 4.6,
        "reviews_count": 175,
        "in_stock": true
      },
      {
        "position": 2,
        "id": "26246806",
        "title": "1200 Thread Count Cotton Blend Watercolor Printed 4-Piece Sheet Set",
        "url": "https://www.macys.com/shop/product/macys-1200-thread-count-cotton-blend-watercolor-printed-4-piece-sheet-sets?ID=26246806",
        "brand": "Macy's",
        "image": null,
        "price": {
          "amount": 59.93,
          "currency": "USD"
        },
        "price_range": null,
        "list_price": {
          "amount": 200,
          "currency": "USD"
        },
        "rating": 4.3,
        "reviews_count": 180,
        "in_stock": true
      }
    ]
  }
}

Responses

Status

Meaning

200

The macy's search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Sephora search.

Sephora search results for a query, in the site's order: id, title, brand, price, rating, review count, image and link. 200 per page; send next_page back as page for more. sort is best_match, price_low, price_high, top_rated, best_selling or newest. Each result is a product shown in one sku, and its id is the product id with that sku (P467208:2417145): it goes straight into POST /v1/products for Sephora. A product with several sizes or shades shows one card, so price is the LOWEST price shown and price_max the highest when no sale is running; when any sku is on sale price_max is null (the card does not say which skus are), and list_price is set only when the card shows one regular and one sale price. Ask for a sku with POST /v1/products for its exact price. rating and reviews_count are Sephora's own (null when unrated). in_stock is always null: search carries no stock. A keyword that matches nothing at all is an empty list (total_results 0), but a nonsense word usually still returns Sephora's closest products. A page past the last, and an answer that is not clearly a list of products or a no-match, is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. price_low and price_high follow the lowest price shown for a product. One of: best_match, price_low, price_high, top_rated, best_selling, newest. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/sephora/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=mascara

Response

{
  "endpoint": "sephora/search",
  "url": "https://www.sephora.com/search?keyword=mascara",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "mascara",
    "page": 1,
    "total_results": 196,
    "next_page": null,
    "results": [
      {
        "position": 1,
        "id": "P467208:2417145",
        "title": "Lash Idôle Lengthening & Volumizing Mascara",
        "url": "https://www.sephora.com/product/lancome-lash-idole-lash-lifting-volumizing-mascara-P467208?skuId=2417145",
        "brand": "Lancôme",
        "image": "https://www.sephora.com/productimages/sku/s2417145-main-zoom.jpg?imwidth=270",
        "price": {
          "amount": 16,
          "currency": "USD"
        },
        "price_max": {
          "amount": 30,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.5,
        "reviews_count": 10787,
        "in_stock": null
      },
      {
        "position": 2,
        "id": "P479863:2638336",
        "title": "Lash Clash Extreme Volume Mascara",
        "url": "https://www.sephora.com/product/yves-saint-laurent-lash-clash-extreme-volume-mascara-P479863?skuId=2638336",
        "brand": "Yves Saint Laurent",
        "image": "https://www.sephora.com/productimages/sku/s2638336-main-zoom.jpg?imwidth=270",
        "price": {
          "amount": 18,
          "currency": "USD"
        },
        "price_max": {
          "amount": 34,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.12,
        "reviews_count": 3607,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The sephora search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Newegg category listing.

Newegg products listed by category, in Newegg's own order (by sales): item number, title, brand, price, list price, rating, review count, stock flag, link and image. Newegg has no keyword search here: query is refused, and no typeahead is offered. category is required and takes one of: components-storage, cpu, memory, motherboard, gpu, computer-case, power-supply, hard-drive, ssd, computer-systems, nas. 100 per page, up to page 75; send next_page back as page for more. sort is not offered. price is the price charged, after Newegg's instant rebate (the rebate is on POST /v1/products), and list_price the price before it when higher; a delisted product has no price. Marketplace sellers' offers are mixed in. rating and reviews_count are Newegg's own and null when unrated; in_stock is Newegg's online stock flag. About 4 in 100 of a category's products never appear when paging it. Each id is what POST /v1/products takes for Newegg. A page past the last, an empty answer, and an answer that is not clearly a list of products is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

category

string

yes

The category to list. Keyword search is not offered, and query is refused. One of: components-storage, cpu, memory, motherboard, gpu, computer-case, power-supply, hard-drive, ssd, computer-systems, nas.

page

integer

—

Results page, 1–75 (100 per page). Default 1.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/newegg/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d category=cpu

Response

{
  "endpoint": "newegg/search",
  "url": "https://www.newegg.com/",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "",
    "page": 1,
    "total_results": 102,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "19-113-877",
        "title": "AMD Ryzen 7 9800X3D - Ryzen 7 9000 Series",
        "url": "https://www.newegg.com/p/N82E16819113877",
        "brand": "AMD",
        "image": "https://c1.neweggimages.com/NeweggImage/ProductImageCompressAll200/19-113-877-01.png",
        "price": {
          "amount": 479,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.8,
        "reviews_count": 745,
        "in_stock": true
      }
    ]
  }
}

Responses

Status

Meaning

200

The newegg category listing as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Ulta Beauty search.

Ulta Beauty search results for a query, in the site's order: item id, title, brand, price, regular price, rating, review count, image and link. 64 per page; send next_page back as page for more. sort is best_match, best_selling, newest, price_low, price_high or rating. Each result is a product shown in one shade or size, and its id is the product id and that sku joined by a colon: it goes straight into POST /v1/products for Ulta, which returns that sku's price and stock. A product whose shades or sizes cost different amounts has no price and a price_range instead. list_price is the regular price of a product marked down. in_stock is always null: search carries no stock. Sponsored placements are left out. rating is a pure rating order (five stars with few reviews first), not a quality ranking. A phrase that matches nothing is an empty list, though a nonsense phrase can still return a few unrelated products. A page past the last is an empty list with the total. An answer that is not clearly a list of products or a count of none is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

sort

string

—

Result order. Each site offers only the orders it supports. One of: best_match, best_selling, price_low, price_high, newest, rating. Default best_match.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/ulta/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=retinol serum"

Response

{
  "endpoint": "ulta/search",
  "url": "https://www.ulta.com/search?search=retinol%20serum",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "retinol serum",
    "page": 1,
    "total_results": 338,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "mkt77006708:77010477",
        "title": "Nightinol Cream",
        "url": "https://www.ulta.com/p/nightinol-cream-mkt77006708?sku=77010477",
        "brand": "WYLYS",
        "image": "https://media.ultainc.com/i/ulta/77010477",
        "price": {
          "amount": 215,
          "currency": "USD"
        },
        "price_range": null,
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": null
      }
    ]
  }
}

Responses

Status

Meaning

200

The ulta beauty search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Whatnot search.

Whatnot listings for a keyword, in the site's order: listing id, title, subtitle, price, buy-it-now or auction format, current bid for an auction, quantity, state, the seller's username, rating and review count, and link. Up to 50 per page; page on with cursor: send next_cursor back as cursor. sort is best_match, newest (newly listed), price_low or price_high; format keeps buy-it-now or auction listings. price is the listing price in dollars, never including shipping or tax; for an auction it is the listing price, not a bid. A price of 900,000 dollars or more is a seller's placeholder and is returned as null (whatnot.placeholderPrice is then true). rating and reviews_count are always null: a listing has none. The rating under whatnot.seller is the SELLER's, across all their sales, not the item's. Pictures are left out (image is null) unless images=true, which makes a page about nine times as costly. Search lists only listings for sale now; POST /v1/products finds a listing by id, a sold or ended one too. Each id is what POST /v1/products takes for Whatnot. A keyword that matches nothing is an empty list (total_results 0); an answer that is not clearly a list of listings or a total of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

cursor

string

—

The next_cursor of the previous page. Whatnot pages by cursor, so there is no page.

sort

string

—

Result order. newest is newly listed. price_high begins with listings whose placeholder price is returned as null. One of: best_match, price_low, price_high, newest. Default best_match.

format

string

—

Only buy-it-now listings, or only auction listings. One of: buy_it_now, auction.

images

boolean

—

Return the first picture as image. Makes a page about nine times as costly. Cost: about 9x. Default false.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/whatnot/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=nike shoes"

Response

{
  "endpoint": "whatnot/search",
  "url": "https://www.whatnot.com/search?query=nike%20shoes",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "nike shoes",
    "page": 1,
    "total_results": 10000,
    "next_page": null,
    "next_cursor": "YXJyYXljb25uZWN0aW9uOjQ5",
    "results": [
      {
        "position": 1,
        "id": "TGlzdGluZ05vZGU6MjUwNTM3MTY3NQ==",
        "title": "Size 10.5m/12w - Nike Vomero Premium 'Black Hot Lava' Womens Running Shoes NEW",
        "url": "https://www.whatnot.com/listing/TGlzdGluZ05vZGU6MjUwNTM3MTY3NQ==",
        "brand": null,
        "image": null,
        "price": {
          "amount": 180,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": true,
        "whatnot": {
          "subtitle": null,
          "format": "buy_it_now",
          "status": "active",
          "quantity": 1,
          "currentBid": null,
          "bidCount": null,
          "seller": {
            "username": "crenyco_snkrs",
            "rating": 5,
            "reviewCount": 45
          },
          "placeholderPrice": false
        }
      },
      {
        "position": 2,
        "id": "TGlzdGluZ05vZGU6MjQ3OTY5MTA2MA==",
        "title": "S06.  Nike Watermelon slides",
        "url": "https://www.whatnot.com/listing/TGlzdGluZ05vZGU6MjQ3OTY5MTA2MA==",
        "brand": null,
        "image": null,
        "price": {
          "amount": 5,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": true,
        "whatnot": {
          "subtitle": "8C ∙ Nike",
          "format": "auction",
          "status": "active",
          "quantity": 1,
          "currentBid": null,
          "bidCount": null,
          "seller": {
            "username": "julesbegules",
            "rating": 5,
            "reviewCount": 1521
          },
          "placeholderPrice": false
        }
      }
    ]
  }
}

Responses

Status

Meaning

200

The whatnot search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Kroger search.

Kroger products for a keyword, best match first: UPC, title, brand, size, regular price, sale price (with its condition), multi-buy, price per unit, stock and pickup flag at the store, rating, review count, link and image. 24 results per request, with no paging and no sort: page and sort are refused. To see beyond the first 24, add brand (the exact brand name, as a result's brand writes it): total_results says how many Kroger has for the query (up to 1,000). Prices and stock are those of one store, the one Kroger picks for the request, reported in kroger.store (locationId, banner, city, state). Send zip to steer the request to that area: it picks the region, not an exact store, so read kroger.store for the store that was priced. price is the regular price of one unit; a sale is in kroger.promo, flagged conditional when it needs a purchase such as buying 3 or more. A keyword that matches nothing is an empty list (total_results 0); an answer that is not clearly a list of products or a total of zero is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list. Each id is what POST /v1/products takes for Kroger.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

brand

string

—

Only products of this brand, written exactly as Kroger's brand of a result (Horizon Organic; capital letters matter). A name that matches no product is an empty list.

banner

string

—

Which Kroger-family store brand to search: kroger (the default) or one of its sister banners. Each has its own stores, so the same query can differ. One of: kroger, ralphs, fredmeyer, kingsoopers, harristeeter, frysfood, smithsfoodanddrug, dillons, marianos, picknsave, qfc.

zip

string

—

A 5-digit US ZIP code. Steers the request to that area, so the store priced is one near there, not necessarily the nearest to the ZIP: kroger.store says which. Unknown ZIP codes are a free 400.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/kroger/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=cinnamon toast crunch"

Response

{
  "endpoint": "kroger/search",
  "url": "https://www.kroger.com/search?query=cinnamon%20toast%20crunch",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "cinnamon toast crunch",
    "page": 1,
    "total_results": 11,
    "next_page": null,
    "results": [
      {
        "position": 1,
        "id": "0001600012254",
        "title": "General Mills Cinnamon Toast Crunch™ Cereal",
        "url": "https://www.kroger.com/p/general-mills-cinnamon-toast-crunch-cereal/0001600012254",
        "brand": "General Mills",
        "image": "https://www.kroger.com/product/images/large/front/0001600012254",
        "price": {
          "amount": 3.99,
          "currency": "USD"
        },
        "list_price": null,
        "rating": 4.8,
        "reviews_count": 2476,
        "in_stock": true,
        "kroger": {
          "size": "12 oz",
          "soldBy": "unit",
          "unitPrice": "$0.33/oz",
          "multiBuy": null,
          "promo": {
            "price": {
              "amount": 3.79,
              "currency": "USD"
            },
            "expiresAt": "2026-11-18T04:59:59.999Z",
            "conditional": true,
            "condition": "Save $2 each when you buy 3 or more"
          },
          "stockLevel": "HIGH",
          "available": 52,
          "pickupSellable": true,
          "variantGroupId": "1578351442723527"
        }
      }
    ],
    "kroger": {
      "banner": "kroger",
      "store": {
        "locationId": "01100439",
        "banner": "kroger",
        "city": "Waycross",
        "state": "GA"
      },
      "brand": null,
      "shown": 1
    }
  }
}

Responses

Status

Meaning

200

The kroger search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Home Depot search.

Home Depot Canada products for a keyword, in the site's order: item number, title, brand, price in Canadian dollars, earlier price, rating, review count, stock, model, aisle and bay, link and image. Up to 40 per page; send next_page back as page for more. Prices and stock are those of one store: send store (a store number such as 7222) or postal_code (a Canadian postal code: the store nearest to it is used), and read homedepot.store for the store that was priced; with neither, the default store is used (Fort Saskatchewan, AB). A store number that does not exist, or a postal code with no store near it, is a free 404. sort is relevance, price_low, price_high or rating. price is the price at the store; list_price is the earlier price of a marked-down product, null otherwise. rating and reviews_count are Home Depot's own and null for a product with no reviews. in_stock is true when the product is in stock in the store or online, false when it is out in both, null when neither is given; the unit counts are homedepot.stockAtStore and homedepot.stockOnline. Each id is what POST /v1/products takes for Home Depot. A keyword that matches nothing is not an empty list: Home Depot answers with one loosely matching product (total_results 1). The list is empty only when total_results is 0, and an answer that is not clearly a list of products or a total of zero is a failure (502 TARGET_FAILED, not charged, retry it).

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–250 (40 products each). Default 1.

sort

string

—

Result order: relevance is Home Depot's own, price_low and price_high by price at the store, rating its best rated first. One of: relevance, price_low, price_high, rating. Default relevance.

store

string

—

A Home Depot store number (7222). Prices and stock are those of this store. Default: store 7222 (Fort Saskatchewan, AB). An unknown store is a free 404.

postal_code

string

—

A Canadian postal code (M5V 2T6): the nearest store is used. Not together with store. A postal code with no store near it is a free 404.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/homedepot/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d query=drill

Response

{
  "endpoint": "homedepot/search",
  "url": "https://www.homedepot.ca/search?q=drill",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "drill",
    "page": 1,
    "total_results": 4232,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "1001686659",
        "title": "18V ONE+ Cordless 1/2 in. Drill/Driver Kit with (1) 1.5 Ah Battery and Charger",
        "url": "https://www.homedepot.ca/product/ryobi-18v-one-cordless-1-2-in-drill-driver-kit-with-1-1-5-ah-battery-and-charger/1001686659",
        "brand": "RYOBI",
        "image": "https://images.homedepot.ca/productimages/p_1001686659.jpg",
        "price": {
          "amount": 78,
          "currency": "CAD"
        },
        "list_price": null,
        "rating": 4.76,
        "reviews_count": 2533,
        "in_stock": true,
        "homedepot": {
          "model": "PCL206K1X",
          "originalPrice": null,
          "savingsPercent": null,
          "stockAtStore": {
            "status": "in_stock",
            "quantity": 15
          },
          "stockOnline": {
            "status": "in_stock",
            "quantity": 389
          },
          "aisle": "9",
          "bay": "001"
        }
      },
      {
        "position": 2,
        "id": "1001769719",
        "title": "20V MAX ATOMIC Lithium-Ion Cordless Brushless Compact 1/2-inch Drill/Driver Kit - with 2.0Ah Battery, Charger & Bag",
        "url": "https://www.homedepot.ca/product/dewalt-20v-max-atomic-lithium-ion-cordless-brushless-compact-1-2-inch-drill-driver-kit-with-2-0ah-battery-charger-bag/1001769719",
        "brand": "DEWALT",
        "image": "https://images.homedepot.ca/productimages/p_1001769719.jpg",
        "price": {
          "amount": 118,
          "currency": "CAD"
        },
        "list_price": {
          "amount": 219,
          "currency": "CAD"
        },
        "rating": 4.74,
        "reviews_count": 5997,
        "in_stock": true,
        "homedepot": {
          "model": "DCD794D1",
          "originalPrice": {
            "amount": 219,
            "currency": "CAD"
          },
          "savingsPercent": 46,
          "stockAtStore": {
            "status": "in_stock",
            "quantity": 34
          },
          "stockOnline": {
            "status": "in_stock",
            "quantity": 107
          },
          "aisle": "10",
          "bay": "004"
        }
      }
    ],
    "homedepot": {
      "store": {
        "id": "7222",
        "name": "FORT SASKATCHEWAN",
        "city": "Fort Saskatchewan",
        "province": "AB"
      }
    }
  }
}

Responses

Status

Meaning

200

The home depot search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

Wayfair search.

Wayfair products for a keyword: sku, name, brand, price, list price, rating, review count, stock, link and image. Up to 100 per request (size, 48 by default); send next_page back as page for more. sort is best_match, price_low, price_high or top_rated; sale=true keeps products that are marked down. Results are always returned: a keyword that matches nothing gets Wayfair's popular products instead, so an empty list never means "no match", and total_results is always null because Wayfair gives no reliable match count. Only the first 1,920 results of a query can be reached (page × size at most 1,920). Sponsored products are included and flagged, and can shift between pages, so a product can appear on two pages. price is the price shown on the card and list_price the struck-through price, null when there is none. rating and reviews_count are Wayfair's own and null for a product with no reviews (never 0). in_stock is true or false only when Wayfair says so and null when it does not; wayfair.stock_status is in_stock, low_stock (in stock, but low) or out_of_stock, and wayfair.stock_message is the card's own text ("Low Stock", "13 Left in Stock"). Prices are those for one fixed delivery area. A busy moment can fail a call (502 TARGET_FAILED, not charged): retry it.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page; page × size must be at most 1920. Default 1.

size

integer

—

Results per page, 1–100. A page costs in proportion to its size. Default 48.

sort

string

—

Result order: best_match is Wayfair's own order, price_low and price_high by price, top_rated by review rating. One of: best_match, price_low, price_high, top_rated. Default best_match.

sale

boolean

—

Only products that are marked down. Default false.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/wayfair/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=standing desk lamp"

Response

{
  "endpoint": "wayfair/search",
  "url": "https://www.wayfair.com/keyword.php?keyword=standing%20desk%20lamp",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "standing desk lamp",
    "page": 1,
    "total_results": null,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "W005077765",
        "title": "Dwayne 68.5'' Dimmable LED Task/Reading Floor Lamp with Remote & Touch Control",
        "url": "https://www.wayfair.com/lighting/pdp/ivy-bronx-dwayne-685-dimmable-led-taskreading-floor-lamp-with-remote-touch-control-w005077765.html?piid=129541178",
        "brand": "Ivy Bronx",
        "image": "https://secure.img1-fg.wfcdn.com/im/00000000/resize-h400-w400%5Ecompr-r85/2151/215129689/image.jpg",
        "price": {
          "amount": 55.99,
          "currency": "USD"
        },
        "list_price": {
          "amount": 79.99,
          "currency": "USD"
        },
        "rating": 4.69,
        "reviews_count": 1385,
        "in_stock": true,
        "sponsored": false,
        "wayfair": {
          "stock_status": "in_stock",
          "stock_message": "13 Left in Stock"
        }
      },
      {
        "position": 2,
        "id": "W006666886",
        "title": "Jernell 70\" LED Dimmable Torchiere & Reading Floor Lamp with Remote Control",
        "url": "https://www.wayfair.com/lighting/pdp/latitude-run-jernell-70-led-dimmable-torchiere-reading-floor-lamp-with-remote-control-w006666886.html?piid=1270286859",
        "brand": "Latitude Run®",
        "image": "https://secure.img1-fg.wfcdn.com/im/00000000/resize-h400-w400%5Ecompr-r85/2697/269735487/image.jpg",
        "price": {
          "amount": 72.99,
          "currency": "USD"
        },
        "list_price": {
          "amount": 110,
          "currency": "USD"
        },
        "rating": 4.61,
        "reviews_count": 1669,
        "in_stock": false,
        "sponsored": false,
        "wayfair": {
          "stock_status": "out_of_stock",
          "stock_message": "Out of Stock"
        }
      }
    ]
  }
}

Responses

Status

Meaning

200

The wayfair search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

GET /v1/structured/shopify/catalog

Shopify store catalog.

A page of a Shopify store's products, in the store's own order: product id (<hostname>/<handle>), title, vendor (as brand), product type, tags, link, first image, lowest variant price, compare-at price, each variant's price and availability flag, and publish and update dates. Up to 250 products per page; page moves through the catalog, and collection (a collection handle) lists one collection instead. query filters the page you fetched, it does not search the store: the store has no keyword search, so only the products of that page whose title, vendor, product type or tags contain every word are returned. Walk the pages to search a whole store. query echoes the filter (empty when there is none), total_results is always null (the store does not say how many products it has), and next_page is set only when the page was full, so the page after the last one is empty. Prices carry no currency (currency is null): the store's own currency applies. Each row also has a shopify object: handle, product id, vendor, product type, tags, every variant (id, sku, title, price, compareAtPrice, available) and the publish and update dates. price is the lowest variant price and list_price the compare-at price of that variant when it is higher, else null. in_stock is true when any variant is available, false when none is, and null when the store does not say; quantities are never given. A store that is not on Shopify, keeps its catalog private or is password protected is a free 404 NOT_FOUND; an answer that is not a product list is a failure (502 TARGET_FAILED, not charged, retry it). Each id is what POST /v1/products takes for Shopify stores.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

domain

string

yes

The store hostname in lowercase, e.g. allbirds.com. Stores on a *.myshopify.com name work too.

collection

string

—

A collection handle (the part after /collections/ in the store's link): list that collection instead of the whole store. An unknown collection is a 404.

page

integer

—

Catalog page, 1–1000 (250 products each). An empty page is the end. Default 1.

limit

integer

—

Products per page, 1–250. Default 250.

query

string

—

Keep only the products of this page whose title, vendor, product type or tags contain every word. It filters one page, not the store.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/shopify/catalog" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d domain=allbirds.com

Response

{
  "endpoint": "shopify/catalog",
  "url": "https://undefeated.com/collections/all",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "",
    "page": 1,
    "total_results": null,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "undefeated.com/adidas-wmns-taekwondo-mei-ballet-sanpin-owhite-gum5",
        "title": "ADIDAS WMNS TAEKWONDO MEI BALLET - SANPIN/ OWHITE/ GUM5",
        "url": "https://undefeated.com/products/adidas-wmns-taekwondo-mei-ballet-sanpin-owhite-gum5",
        "brand": "ADIDAS",
        "image": "https://cdn.shopify.com/s/files/1/0282/5850/files/footwear_adidas_wmns-taekwondo-mei-ballet_IH6915.view_1.jpg?v=1771891297",
        "price": {
          "amount": 47.5,
          "currency": null
        },
        "list_price": {
          "amount": 95,
          "currency": null
        },
        "in_stock": true,
        "shopify": {
          "domain": "undefeated.com",
          "handle": "adidas-wmns-taekwondo-mei-ballet-sanpin-owhite-gum5",
          "productId": 6702088290565,
          "vendor": "ADIDAS",
          "productType": "Womens Footwear",
          "tags": ["26.Q1", "adidas", "MEMORIAL_26", "size-8-5", "womens-footwear"],
          "variants": [
            {
              "id": 39751807336709,
              "sku": "IH6915---6",
              "title": "6",
              "price": 47.5,
              "compareAtPrice": 95,
              "available": false
            },
            {
              "id": 39751807369477,
              "sku": "IH6915---6.5",
              "title": "6.5",
              "price": 47.5,
              "compareAtPrice": 95,
              "available": false
            }
          ],
          "publishedAt": "2026-11-04T17:22:07.000Z",
          "updatedAt": "2026-11-05T19:27:03.000Z"
        }
      }
    ]
  }
}

Responses

Status

Meaning

200

The shopify store catalog as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

GET /v1/structured/reddit/posts

Reddit posts.

A subreddit's posts, newest (or hot, top, rising) first: title, author, score, comment count, upvote ratio, post type, flair and text. About 25 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

subreddit

string

yes

The subreddit, e.g. sneakers (also r/sneakers or its URL).

sort

string

—

Listing order. One of: new, hot, top, rising. Default new.

time

string

—

With sort=top: the window. One of: hour, day, week, month, year, all. Default day.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/reddit/posts" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d subreddit=webscraping \
  -d sort=new

Response

{
  "endpoint": "reddit/posts",
  "url": "https://www.reddit.com/r/webscraping/new/",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "subreddit": "webscraping",
    "sort": "new",
    "time": null,
    "posts": [
      {
        "id": "1xn96sv",
        "subreddit": "webscraping",
        "title": "Anyone doing webscraping with an antidetect browser?",
        "author": "example_user",
        "url": "https://www.reddit.com/r/webscraping/comments/1xn96sv/…/",
        "link": null,
        "created_at": "2026-11-03T23:51:15.577Z",
        "score": 5,
        "comments": 8,
        "upvote_ratio": 1,
        "type": "text",
        "domain": "self.webscraping",
        "flair": "Getting started",
        "text": "Hello. I would like to add some plugins for scraping…"
      }
    ],
    "next_cursor": "dDNfMXhncncybg=="
  }
}

Responses

Status

Meaning

200

The reddit posts as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.subreddit

string

—

data.sort

string

—

data.time

string or null

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

Reddit search.

Posts matching a query, across Reddit or in one subreddit: title, author, subreddit, time and text. Up to 100 per page; page on with cursor. Sort by new to watch for mentions.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

subreddit

string

—

Search only this subreddit, e.g. sneakers.

sort

string

—

Result order. One of: relevance, new, top, comments. Default relevance.

time

string

—

Only posts from this window. One of: hour, day, week, month, year, all. Default all.

limit

integer

—

Results per page, 1–100. Default 25.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/reddit/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping api" \
  -d sort=new

Response

{
  "endpoint": "reddit/search",
  "url": "https://www.reddit.com/search/?q=web+scraping+api&sort=new",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "web scraping api",
    "subreddit": null,
    "sort": "new",
    "time": "all",
    "results": [
      {
        "id": "1xnfagb",
        "subreddit": "indiehackers",
        "title": "Frustrated with SEO tool pricing, so I built this",
        "author": "example_user",
        "url": "https://www.reddit.com/r/indiehackers/comments/1xnfagb/…/",
        "created_at": "2026-11-04T04:48:21.000Z",
        "text": "I have been on the starter plan for a year…"
      }
    ],
    "next_cursor": "t3_1xnfagb"
  }
}

Responses

Status

Meaning

200

The reddit search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.subreddit

string or null

—

data.sort

string

—

data.time

string or null

—

data.results

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

GET /v1/structured/reddit/comments

Reddit comments.

A post's comments (send post), or a subreddit's newest comments (send subreddit): author, time, text and the post each one is on. Up to 100 per page.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

post

string

—

A post's id (e.g. 1xn96sv) or URL: its comments.

subreddit

string

—

A subreddit, e.g. sneakers: its newest comments. Send this or post.

sort

string

—

With post: the thread's order. One of: best, top, new, old, controversial. Default best.

limit

integer

—

Results per page, 1–100. Default 25.

cursor

string

—

With subreddit: the previous page's next_cursor.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/reddit/comments" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d subreddit=webscraping

Response

{
  "endpoint": "reddit/comments",
  "url": "https://www.reddit.com/r/webscraping/comments/",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "subreddit": "webscraping",
    "post": null,
    "comments": [
      {
        "id": "19s3yr8g8su0x",
        "post_id": "1xn96sv",
        "post_title": "Anyone doing webscraping with an antidetect browser?",
        "subreddit": "webscraping",
        "author": "example_user",
        "url": "https://www.reddit.com/r/webscraping/comments/1xn96sv/…/19s3yr8g8su0x/",
        "created_at": "2026-11-04T03:45:28.000Z",
        "text": "Python and Playwright here."
      }
    ],
    "next_cursor": "t1_19s3yr8g8su0x"
  }
}

Responses

Status

Meaning

200

The reddit comments as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.subreddit

string or null

Set for a subreddit's newest comments.

data.post

any

Set for one post's comments: the post itself.

data.comments

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

Bing search.

A Bing web results page: each organic result with its position, title, URL, displayed URL and snippet, plus the estimated total. Ten per page.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–100. Default 1.

country

string

—

Two-letter country to search as. Default us.

language

string

—

Interface language, e.g. en, de, pt-BR. Default en.

zip

string

—

A 5-digit US ZIP code. Results reflect that area (local prices, stock and nearby results). Unknown ZIP codes are a free 400.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/bing/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping api" \
  -d country=us

Response

{
  "endpoint": "bing/search",
  "url": "https://www.bing.com/search?q=web+scraping+api",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "web scraping api",
    "page": 1,
    "total_results": 70400,
    "results": [
      {
        "position": 1,
        "title": "Web Scraping API — Example",
        "url": "https://www.example.com/",
        "displayed_url": "https://www.example.com",
        "snippet": "Public web data, from request to dataset…"
      }
    ]
  }
}

Responses

Status

Meaning

200

The bing search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

A web results page: the organic results in page order.

data.query

string

—

data.page

integer

—

data.total_results

integer or null

The engine's own estimate, when it shows one.

data.results

object[]

—

DuckDuckGo search.

A DuckDuckGo web results page: each organic result with its position, title, URL, displayed URL and snippet (ads left out). About 10 results on page 1 and 15 on later pages; pages 1–5.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

page

integer

—

Results page, 1–5. A later page costs about as much as every page before it together. Default 1.

region

string

—

Region and language, e.g. us-en, uk-en, de-de; wt-wt for none. Default us-en.

zip

string

—

A 5-digit US ZIP code. Results reflect that area (local prices, stock and nearby results). Unknown ZIP codes are a free 400.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/duckduckgo/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping api" \
  -d region=us-en

Response

{
  "endpoint": "duckduckgo/search",
  "url": "https://duckduckgo.com/?q=web+scraping+api&kl=us-en",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "web scraping api",
    "page": 1,
    "total_results": null,
    "results": [
      {
        "position": 1,
        "title": "15 Best Web Scraping APIs in 2026",
        "url": "https://example.org/guides/best-web-scraping-apis/",
        "displayed_url": "example.org/guides/best-web-scraping-apis/",
        "snippet": "Which web scraping API handles JavaScript-heavy sites best?…"
      }
    ]
  }
}

Responses

Status

Meaning

200

The duckduckgo search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

A web results page: the organic results in page order.

data.query

string

—

data.page

integer

—

data.total_results

integer or null

The engine's own estimate, when it shows one.

data.results

object[]

—

GET /v1/structured/gemini/answer

Gemini answer.

Gemini's answer to a prompt as a visitor who is not signed in sees it: the answer text in markdown, the model, the sources it cites in order (each the page itself), whether it declined, and what it searched for when it says.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

prompt

string

yes

What to ask, up to 2,000 characters.

country

string

—

Two-letter country to ask from. Default us.

zip

string

—

A 5-digit US ZIP code. Results reflect that area (local prices, stock and nearby results). Unknown ZIP codes are a free 400.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/gemini/answer" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "prompt=What is the best CRM for a small business?" \
  -d country=us

Response

{
  "endpoint": "gemini/answer",
  "url": "https://gemini.google.com/app",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "prompt": "What is the best CRM for a small business?",
    "model": "3.5 Flash-Lite",
    "text": "The best CRM depends on your team size and budget. **HubSpot CRM** has a generous free tier, **Zoho Bigin** suits micro-businesses, and **Pipedrive** is built around the sales pipeline.",
    "citations": [
      {
        "position": 1,
        "url": "https://www.pcmag.com/picks/the-best-crm-software",
        "title": "The Best CRM Software We've Tested for 2026 | PCMag",
        "domain": "pcmag.com"
      },
      {
        "position": 2,
        "url": "https://zapier.com/blog/best-crms-for-small-business/",
        "title": "The 11 Best CRMs for Small Business in 2026 - Zapier",
        "domain": "zapier.com"
      }
    ],
    "refused": false,
    "search_queries": null
  }
}

Responses

Status

Meaning

200

The gemini answer as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

An AI assistant's answer to a prompt, as a visitor sees it.

data.prompt

string

—

data.model

string or null

The model that answered, as the assistant names it.

data.text

string

The answer, markdown.

data.citations

object[]

Sources in the order the assistant lists them, one per URL, each the page itself.

data.refused

boolean

The assistant declined to answer.

data.search_queries

any

What it searched for, when it says; null when it does not.

GET /v1/structured/chatgpt/answer

ChatGPT answer.

The answer ChatGPT gives an anonymous visitor to a prompt, with web search: the text as markdown, the pages it cites in order of appearance, the searches it ran, and whether it declined.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

prompt

string

yes

What to ask, up to 2,000 characters.

country

string

—

Two-letter country the visitor appears to be in. Default us.

zip

string

—

A 5-digit US ZIP code. Results reflect that area (local prices, stock and nearby results). Unknown ZIP codes are a free 400.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/chatgpt/answer" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "prompt=best project management tools for small teams" \
  -d country=us

Response

{
  "endpoint": "chatgpt/answer",
  "url": "https://chatgpt.com/",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "prompt": "best project management tools for small teams",
    "model": "gpt-6",
    "text": "For a small team, shortlist **ClickUp**, **Asana** and **Trello** [1][2].\n\n- **ClickUp:** one workspace for tasks, docs and goals.\n- **Asana:** clear ownership and deadlines.\n- **Trello:** simple boards.",
    "citations": [
      {
        "position": 1,
        "url": "https://example.com/best-project-management-software",
        "title": "Best project management software for small teams",
        "domain": "example.com"
      },
      {
        "position": 2,
        "url": "https://example.org/guides/trello-vs-asana",
        "title": "Trello vs Asana",
        "domain": "example.org"
      }
    ],
    "refused": false,
    "search_queries": ["best project management software for small teams 2026"]
  }
}

Responses

Status

Meaning

200

The chatgpt answer as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

An AI assistant's answer to a prompt, as a visitor sees it.

data.prompt

string

—

data.model

string or null

The model that answered, as the assistant names it.

data.text

string

The answer, markdown.

data.citations

object[]

Sources in the order the assistant lists them, one per URL, each the page itself.

data.refused

boolean

The assistant declined to answer.

data.search_queries

any

What it searched for, when it says; null when it does not.

Bluesky search.

Bluesky posts matching a query, newest or top first: author, text, likes, replies, reposts, tags, links and images. Up to 100 per page; page on with cursor. Sort by latest to watch for mentions.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

sort

string

—

Result order. One of: latest, top. Default latest.

limit

integer

—

Posts per page, 1–100. Default 25.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/bluesky/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping" \
  -d sort=latest

Response

{
  "endpoint": "bluesky/search",
  "url": "https://bsky.app/search?q=web%20scraping",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "at://did:plc:example/app.bsky.feed.post/3mzhmrhqbhq2n",
        "url": "https://bsky.app/profile/example.bsky.social/post/3mzhmrhqbhq2n",
        "author": "example.bsky.social",
        "author_name": "Example",
        "title": null,
        "text": "Anyone have a web scraping API that handles retries for you?",
        "created_at": "2026-11-04T05:30:54.000Z",
        "likes": 4,
        "replies": 2,
        "reposts": 0,
        "tags": ["webscraping"],
        "community": null,
        "link": null,
        "media": []
      }
    ],
    "next_cursor": "eyJzIjpbMTc5Mzc1OTExNjAwMF19"
  }
}

Responses

Status

Meaning

200

The bluesky search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

GET /v1/structured/bluesky/posts

Bluesky posts.

An account's posts, newest first (its reposts of others left out): text, likes, replies, reposts, tags, links and images. Up to 100 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

handle

string

yes

The account, e.g. bsky.app (also @bsky.app or its profile URL).

limit

integer

—

Posts per page, 1–100. Default 25.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/bluesky/posts" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d handle=bsky.app

Response

{
  "endpoint": "bluesky/posts",
  "url": "https://bsky.app/profile/bsky.app",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "at://did:plc:example/app.bsky.feed.post/3mzhhvhjfwk22",
        "url": "https://bsky.app/profile/bsky.app/post/3mzhhvhjfwk22",
        "author": "bsky.app",
        "author_name": "Bluesky",
        "title": null,
        "text": "New this week: …",
        "created_at": "2026-11-03T18:02:11.000Z",
        "likes": 5210,
        "replies": 340,
        "reposts": 610,
        "tags": [],
        "community": null,
        "link": "https://bsky.social/about/blog",
        "media": []
      }
    ],
    "next_cursor": "2026-11-03T18:02:11.000Z"
  }
}

Responses

Status

Meaning

200

The bluesky posts as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

GET /v1/structured/mastodon/hashtag

Mastodon hashtag.

Public posts with a hashtag on a Mastodon server (mastodon.social unless you name another), newest first: author, text, likes, replies, boosts, tags, links and media. Up to 40 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

tag

string

yes

The hashtag, with or without #, e.g. webscraping.

instance

string

—

The Mastodon server to read, e.g. fosstodon.org. It also shows posts from servers it federates with. Default mastodon.social.

limit

integer

—

Posts per page, 1–40. Default 20.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/mastodon/hashtag" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d tag=webscraping

Response

{
  "endpoint": "mastodon/hashtag",
  "url": "https://mastodon.social/tags/webscraping",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "117553103172691630",
        "url": "https://mastodon.social/@example/117553103172691630",
        "author": "example@mastodon.social",
        "author_name": "Example",
        "title": null,
        "text": "Pages come back blank behind an authenticated proxy? Here is what fixed it for us.",
        "created_at": "2026-11-03T15:00:04.979Z",
        "likes": 3,
        "replies": 0,
        "reposts": 1,
        "tags": ["webscraping", "python"],
        "community": null,
        "link": null,
        "media": []
      }
    ],
    "next_cursor": "117553103172691630"
  }
}

Responses

Status

Meaning

200

The mastodon hashtag as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

Lemmy search.

Lemmy posts matching a query on a Lemmy server (lemmy.world unless you name another): title, author, community, score, comment count, text and link. Up to 50 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

instance

string

—

The Lemmy server to read, e.g. lemmy.ml. It also has the communities it federates with. Default lemmy.world.

sort

string

—

Result order. One of: new, hot, active, top_day, top_week, top_month, top_year, top_all, most_comments. Default new.

limit

integer

—

Posts per page, 1–50. Default 20.

cursor

string

—

The next_cursor of the previous page (a page number).

Request

curl -G "https://api.scrapelyserp.com/v1/structured/lemmy/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping"

Response

{
  "endpoint": "lemmy/search",
  "url": "https://lemmy.world/search?q=web%20scraping&type=Posts",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "53928115",
        "url": "https://lemmy.world/post/53928115",
        "author": "example@lemmy.world",
        "author_name": null,
        "title": "Outlets sue a browser maker over alleged content scraping",
        "text": "The suit says the content was redistributed to customers…",
        "created_at": "2026-11-03T05:29:22.928Z",
        "likes": 218,
        "replies": 45,
        "reposts": null,
        "tags": [],
        "community": "technology@lemmy.world",
        "link": "https://example.com/news/scraping-lawsuit",
        "media": []
      }
    ],
    "next_cursor": "2"
  }
}

Responses

Status

Meaning

200

The lemmy search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

GET /v1/structured/lemmy/posts

Lemmy community posts.

A Lemmy community's posts, newest (or hot, top…) first: title, author, score, comment count, text and link. Up to 50 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

community

string

yes

The community, e.g. technology, or one on another server: technology@lemmy.ml.

instance

string

—

The Lemmy server to read, e.g. lemmy.ml. It also has the communities it federates with. Default lemmy.world.

sort

string

—

Result order. One of: new, hot, active, top_day, top_week, top_month, top_year, top_all, most_comments. Default new.

limit

integer

—

Posts per page, 1–50. Default 20.

cursor

string

—

The next_cursor of the previous page (a page number).

Request

curl -G "https://api.scrapelyserp.com/v1/structured/lemmy/posts" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d community=technology

Response

{
  "endpoint": "lemmy/posts",
  "url": "https://lemmy.world/c/technology",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "53928115",
        "url": "https://lemmy.world/post/53928115",
        "author": "example@lemmy.world",
        "author_name": null,
        "title": "Outlets sue a browser maker over alleged content scraping",
        "text": "",
        "created_at": "2026-11-03T05:29:22.928Z",
        "likes": 218,
        "replies": 45,
        "reposts": null,
        "tags": [],
        "community": "technology@lemmy.world",
        "link": "https://example.com/news/scraping-lawsuit",
        "media": []
      }
    ],
    "next_cursor": "2"
  }
}

Responses

Status

Meaning

200

The lemmy community posts as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

Discourse search.

Posts matching a query on any public Discourse forum: topic title, author, excerpt, likes, tags and category. 50 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

forum

string

yes

The forum’s domain, e.g. meta.discourse.org (or any URL on it).

query

string

yes

The search terms.

cursor

string

—

The next_cursor of the previous page (a page number).

Request

curl -G "https://api.scrapelyserp.com/v1/structured/discourse/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d forum=meta.discourse.org \
  -d query=webhooks

Response

{
  "endpoint": "discourse/search",
  "url": "https://meta.discourse.org/search?q=webhooks",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "257177",
        "url": "https://meta.discourse.org/t/trigger-a-zapier-task-with-discourse-webhooks/56753/1",
        "author": "example",
        "author_name": null,
        "title": "Trigger a Zapier task with Discourse Webhooks",
        "text": "Want to use Discourse Webhooks to trigger a task? Let's get started!…",
        "created_at": "2017-02-01T22:11:22.521Z",
        "likes": 32,
        "replies": 29,
        "reposts": null,
        "tags": ["webhooks"],
        "community": "Documentation",
        "link": null,
        "media": []
      }
    ],
    "next_cursor": "2"
  }
}

Responses

Status

Meaning

200

The discourse search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

GET /v1/structured/discourse/topic

Discourse topic.

A topic's posts in order on any public Discourse forum, the opening post first: author, text, likes and replies. 20 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

forum

string

yes

The forum’s domain, e.g. meta.discourse.org (or any URL on it).

topic

string

yes

The topic’s id, e.g. 49045, or its URL.

cursor

string

—

The next_cursor of the previous page (a page number).

Request

curl -G "https://api.scrapelyserp.com/v1/structured/discourse/topic" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d forum=meta.discourse.org \
  -d topic=49045

Response

{
  "endpoint": "discourse/topic",
  "url": "https://meta.discourse.org/t/49045",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "217834",
        "url": "https://meta.discourse.org/t/setting-up-webhooks/49045/1",
        "author": "example",
        "author_name": "Example",
        "title": "Setting up webhooks",
        "text": "A webhook is a way to notify external services about changes…",
        "created_at": "2016-08-23T05:36:09.935Z",
        "likes": 74,
        "replies": 3,
        "reposts": null,
        "tags": ["howto"],
        "community": null,
        "link": null,
        "media": []
      }
    ],
    "next_cursor": null
  }
}

Responses

Status

Meaning

200

The discourse topic as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

GET /v1/structured/tumblr/tagged

Tumblr tagged posts.

Tumblr posts with a tag, newest or top first: blog, text, notes, reblogs, tags, links and images. Up to 20 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

tag

string

yes

The tag, e.g. webscraping.

sort

string

—

Result order. One of: recent, top. Default recent.

limit

integer

—

Posts per page, 1–20. Default 20.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/tumblr/tagged" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d tag=webscraping

Response

{
  "endpoint": "tumblr/tagged",
  "url": "https://www.tumblr.com/tagged/webscraping?sort=recent",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "832269873172381696",
        "url": "https://www.tumblr.com/example/832269873172381696/selenium-will-tell-you-everything-is-fine",
        "author": "example",
        "author_name": null,
        "title": null,
        "text": "selenium will tell you everything is fine. no exception. no error…",
        "created_at": "2026-11-03T15:00:02.000Z",
        "likes": 6,
        "replies": 0,
        "reposts": 2,
        "tags": ["webscraping", "python"],
        "community": null,
        "link": null,
        "media": []
      }
    ],
    "next_cursor": "VGh4j_eC7tsoXm676sVywGIYynqF"
  }
}

Responses

Status

Meaning

200

The tumblr tagged posts as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

Tumblr search.

Tumblr posts matching a query, newest or top first: blog, text, notes, reblogs, tags, links and images. Up to 20 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

sort

string

—

Result order. One of: recent, top. Default recent.

limit

integer

—

Posts per page, 1–20. Default 20.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/tumblr/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping"

Response

{
  "endpoint": "tumblr/search",
  "url": "https://www.tumblr.com/search/web%20scraping",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "posts": [
      {
        "id": "832269873172381696",
        "url": "https://www.tumblr.com/example/832269873172381696/selenium-will-tell-you-everything-is-fine",
        "author": "example",
        "author_name": null,
        "title": null,
        "text": "selenium will tell you everything is fine. no exception. no error…",
        "created_at": "2026-11-03T15:00:02.000Z",
        "likes": 6,
        "replies": 0,
        "reposts": 2,
        "tags": ["selenium", "web scraping"],
        "community": null,
        "link": null,
        "media": []
      }
    ],
    "next_cursor": "VGh4j_eC7tsoXm676sVywGIYynqF"
  }
}

Responses

Status

Meaning

200

The tumblr search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.posts

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

Hacker News search.

Hacker News stories and comments matching a query, by relevance or newest first, with filters for type, author, story, points and dates: title, link, author, points, comment count, text and time. Up to 100 per page; page on with cursor. A query reaches only its first 1,000 results.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

—

The search terms. Leave it out to list by the filters alone.

type

string

—

story, comment, ask_hn (Ask HN), show_hn (Show HN) or all. One of: story, comment, ask_hn, show_hn, all. Default story.

sort

string

—

relevance, or date for newest first (to watch for mentions). One of: relevance, date. Default relevance.

author

string

—

Only this user’s items, e.g. pg.

story

string

—

Only items under this story (its id or link): with type=comment, its comments.

min_points

integer

—

Only items with at least this many points. Comments have no points.

since

string

—

Only items from this time on: 2026-01-31, 2026-01-31T12:00:00Z or Unix seconds.

until

string

—

Only items up to this time, in the same forms.

limit

integer

—

Results per page, 1–100. Default 30.

cursor

string

—

The next_cursor of the previous page (a page number).

Request

curl -G "https://api.scrapelyserp.com/v1/structured/hackernews/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping" \
  -d sort=date

Response

{
  "endpoint": "hackernews/search",
  "url": "https://news.ycombinator.com/",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "rust",
    "type": "story",
    "sort": "relevance",
    "total": 61311,
    "results": [
      {
        "id": "22238335",
        "type": "story",
        "title": "Why Discord is switching from Go to Rust",
        "url": "https://blog.discordapp.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f",
        "hn_url": "https://news.ycombinator.com/item?id=22238335",
        "author": "Sikul",
        "points": 1582,
        "comments": 642,
        "text": null,
        "created_at": "2020-02-04T17:30:40.000Z",
        "story_id": "22238335",
        "story_title": null,
        "parent_id": null
      }
    ],
    "next_cursor": "2"
  }
}

Responses

Status

Meaning

200

The hacker news search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string or null

—

data.type

string

—

data.sort

string

—

data.total

integer

Every match. Only the first 1,000 can be paged to.

data.results

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end of the first 1,000.

GET /v1/structured/hackernews/items

Hacker News items.

Up to 100 Hacker News items by id, in one call: title, link, author, points, comment count, text, time and the ids of its replies. Ids that are not items come back in not_found.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

ids

string

yes

Comma-separated item ids (stories, comments, jobs, polls), e.g. 8863,2921983; links to items work too. Up to 100.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/hackernews/items" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "ids=8863,2921983"

Response

{
  "endpoint": "hackernews/items",
  "url": "https://news.ycombinator.com/item?id=8863",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "items": [
      {
        "id": "8863",
        "type": "story",
        "title": "My YC app: Dropbox - Throw away your USB drive",
        "url": "http://www.getdropbox.com/u/2/screencast.html",
        "hn_url": "https://news.ycombinator.com/item?id=8863",
        "author": "dhouston",
        "points": 104,
        "comments": 71,
        "text": null,
        "created_at": "2007-04-04T19:16:40.000Z",
        "parent_id": null,
        "reply_ids": ["9224", "8917", "8884"],
        "deleted": false,
        "dead": false
      }
    ],
    "not_found": []
  }
}

Responses

Status

Meaning

200

The hacker news items as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.items

object[]

In the order asked.

data.not_found

string[]

Asked-for ids that are not items.

GET /v1/structured/devto/articles

Dev.to articles.

Dev.to articles, newest first, or the most popular of the last days: title, summary, author, tags, reactions, comment count, reading time and link. Narrow by tag or username. Dev.to has no keyword search, so there is none here. Up to 100 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

tag

string

—

Only articles with this tag, e.g. webdev. An unknown tag lists nothing.

username

string

—

Only this author’s articles, e.g. ben. An unknown author lists nothing.

top

integer

—

The most-reacted articles of the last N days (1–366) instead of the newest.

state

string

—

fresh (new, no reactions yet), rising (gaining reactions) or all. One of: fresh, rising, all.

limit

integer

—

Articles per page, 1–100. Default 30.

cursor

string

—

The next_cursor of the previous page (a page number).

Request

curl -G "https://api.scrapelyserp.com/v1/structured/devto/articles" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d tag=webdev \
  -d top=7

Response

{
  "endpoint": "devto/articles",
  "url": "https://dev.to/t/webdev",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "tag": "webdev",
    "username": null,
    "top": 7,
    "state": null,
    "articles": [
      {
        "id": "4943245",
        "title": "Yes, {} + [] = 0. No, JavaScript Isn’t Broken",
        "description": "JavaScript is a legendary programming language. Created in the mid-1990s in just 10 days, it was born...",
        "url": "https://dev.to/sylwia-lask/yes-0-no-javascript-isnt-broken-14ob",
        "author": "sylwia-lask",
        "author_name": "Sylwia Laskowska",
        "organization": null,
        "published_at": "2026-10-29T20:08:53Z",
        "edited_at": "2026-10-30T13:34:02Z",
        "tags": ["javascript", "webdev", "node", "programming"],
        "reactions": 170,
        "comments": 126,
        "reading_time_minutes": 5,
        "language": "en",
        "cover_image": null,
        "canonical_url": "https://dev.to/sylwia-lask/yes-0-no-javascript-isnt-broken-14ob"
      }
    ],
    "next_cursor": "2"
  }
}

Responses

Status

Meaning

200

The dev.to articles as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.tag

string or null

—

data.username

string or null

—

data.top

integer or null

—

data.state

string or null

—

data.articles

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null when this page came back short.

GET /v1/structured/devto/article

Dev.to article.

One Dev.to article in full: the Markdown body with its title, author, tags, reactions, comment count and dates.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

article

string

yes

The article’s id (e.g. 4943245), its link, or username/slug.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/devto/article" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d article=4943245

Response

{
  "endpoint": "devto/article",
  "url": "https://dev.to/sylwia-lask/yes-0-no-javascript-isnt-broken-14ob",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "id": "4943245",
    "title": "Yes, {} + [] = 0. No, JavaScript Isn’t Broken",
    "description": "JavaScript is a legendary programming language. Created in the mid-1990s in just 10 days, it was born...",
    "url": "https://dev.to/sylwia-lask/yes-0-no-javascript-isnt-broken-14ob",
    "author": "sylwia-lask",
    "author_name": "Sylwia Laskowska",
    "organization": null,
    "published_at": "2026-10-29T20:08:53Z",
    "edited_at": "2026-10-30T13:34:02Z",
    "tags": ["javascript", "webdev", "node", "programming"],
    "reactions": 170,
    "comments": 126,
    "reading_time_minutes": 5,
    "language": "en",
    "cover_image": null,
    "canonical_url": "https://dev.to/sylwia-lask/yes-0-no-javascript-isnt-broken-14ob",
    "body_markdown": "JavaScript is a legendary programming language…"
  }
}

Responses

Status

Meaning

200

The dev.to article as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.id

string

Dev.to's article id.

data.title

string

—

data.description

string or null

The summary Dev.to shows under the title.

data.url

string

—

data.author

string or null

Username.

data.author_name

string or null

—

data.organization

string or null

The organisation it was published under, if any.

data.published_at

string (date-time) or null

—

data.edited_at

string (date-time) or null

—

data.tags

string[]

—

data.reactions

integer or null

Public reactions, all kinds.

data.comments

integer or null

—

data.reading_time_minutes

integer or null

—

data.language

string or null

—

data.cover_image

string or null

—

data.canonical_url

string or null

Where the article was first published, when crossposted.

data.body_markdown

string

The article as Markdown.

Wikipedia search.

Wikipedia pages matching a query, best match first: title, page id, link, a snippet with the match, word count and last edit. Up to 50 per page; page on with cursor.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

yes

The search terms.

lang

string

—

The language edition. One of: en, de, fr, es, it, pt, nl, pl, sv, ru, ja, zh, ar, ko, tr, uk. Default en.

limit

integer

—

Results per page, 1–50. Default 20.

cursor

string

—

The next_cursor of the previous page.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/wikipedia/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=web scraping"

Response

{
  "endpoint": "wikipedia/search",
  "url": "https://en.wikipedia.org/",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "web scraping",
    "lang": "en",
    "total": 2117,
    "results": [
      {
        "title": "Web scraping",
        "page_id": 2696619,
        "url": "https://en.wikipedia.org/wiki/Web_scraping",
        "snippet": "Web scraping, web harvesting, or web data extraction is data scraping used for extracting data from websites. Web scraping software may directly access",
        "word_count": 4123,
        "last_modified": "2026-11-01T23:24:25Z"
      }
    ],
    "next_cursor": "50"
  }
}

Responses

Status

Meaning

200

The wikipedia search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.lang

string

—

data.total

integer

Every match; 0 for a query that matches nothing.

data.results

object[]

—

data.next_cursor

string or null

Pass as cursor for the next page; null at the end.

GET /v1/structured/wikipedia/pages

Wikipedia pages.

Up to 100 Wikipedia pages by title, in one call: the opening text, the short description, the Wikidata id, whether it is a disambiguation page, and the last edit. Redirects are followed and reported. Titles that are not pages come back in not_found.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

titles

string

yes

Page titles separated by |, e.g. Albert Einstein|Web scraping; page links work too. Up to 100.

lang

string

—

The language edition. One of: en, de, fr, es, it, pt, nl, pl, sv, ru, ja, zh, ar, ko, tr, uk. Default en.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/wikipedia/pages" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "titles=Albert Einstein|Web scraping"

Response

{
  "endpoint": "wikipedia/pages",
  "url": "https://en.wikipedia.org/wiki/Mercury",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "lang": "en",
    "pages": [
      {
        "requested": "Mercury",
        "title": "Mercury",
        "page_id": 19007,
        "url": "https://en.wikipedia.org/wiki/Mercury",
        "redirected_from": null,
        "description": "Topics referred to by the same term",
        "extract": "Mercury most commonly refers to:\n\nMercury (planet), the closest planet to the Sun",
        "wikidata_id": "Q48397",
        "disambiguation": true,
        "last_modified": "2026-11-02T03:24:00Z",
        "length": 8268
      }
    ],
    "not_found": []
  }
}

Responses

Status

Meaning

200

The wikipedia pages as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.lang

string

—

data.pages

object[]

In the order asked; two titles that redirect to one page give two entries.

data.not_found

string[]

Asked-for titles that are not pages.

Reverb search.

Reverb listings for a query, a category, or both, in the site's order: listing id, title, make (as brand), listed price, price before a price drop, condition, model, year, finish, category, shop name, offers flag, quantity, shipping price, dates, link and image. 50 per page; send next_page back as page for more. sort is best_match, newest, price_low or price_high; status is available (the default) or sold; condition, min_price / max_price (whole dollars) and category (a category slug such as electric-guitars) narrow the listings. Only the first 2,500 listings of a query can be reached (page 1 to 50), however large total_results says: narrow the query to see more. price is the listed price, on a sold listing too: it is the last price the listing carried, not necessarily what the buyer paid, and Reverb gives no sold price and no sold date. list_price is the price before a price drop, null when the price never dropped. rating and reviews_count are always null: listings have none (the shop's rating is on a product lookup, not in search). in_stock is true for an available listing and false for a sold one. Each id is what POST /v1/products takes for Reverb. A keyword that matches nothing is an empty list (total_results 0); an answer that is not clearly a list of listings in the state asked for, or a total of zero, is a failure (502 TARGET_FAILED, not charged, retry it), not an empty list. A request with neither query nor category is refused.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

query

string

—

The search terms. Required unless category is given.

category

string

—

A Reverb category slug (electric-guitars, effects-and-pedals). Lists that category; query then narrows it.

page

integer

—

Results page, 1–50 (50 listings each: the first 2,500 of a query). Default 1.

sort

string

—

Result order: best_match is Reverb's relevance order, newest just published, price_low and price_high by listed price. One of: best_match, newest, price_low, price_high. Default best_match.

status

string

—

Listings for sale, or sold ones (their last listed price; Reverb gives no sold price or date). One of: available, sold. Default available.

condition

string

—

Only listings in this condition. One of: mint, excellent, very-good, good, fair.

min_price

string

—

Lowest listed price, in whole dollars.

max_price

string

—

Highest listed price, in whole dollars.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/reverb/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "query=boss ds-1"

Response

{
  "endpoint": "reverb/search",
  "url": "https://reverb.com/marketplace?query=boss%20ds-1",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "query": "boss ds-1",
    "page": 1,
    "total_results": 979,
    "next_page": 2,
    "results": [
      {
        "position": 1,
        "id": "101847259",
        "title": "Keeley Boss DS-1 Distortion Mod",
        "url": "https://reverb.com/item/101847259-keeley-boss-ds-1-distortion-mod",
        "brand": "Keeley",
        "image": "https://rvb-img.reverb.com/i/s--aXAmI2rm--/quality=medium-low,height=800,width=800,fit=contain/bd04a110-5204-4f71-84fe-320e0e5ff53a.jpeg",
        "price": {
          "amount": 125,
          "currency": "USD"
        },
        "list_price": null,
        "rating": null,
        "reviews_count": null,
        "in_stock": true,
        "reverb": {
          "status": "available",
          "condition": "Very Good",
          "make": "Keeley",
          "model": "Boss DS-1 Distortion with Ultra Mod",
          "year": "2010s",
          "finish": "Orange",
          "category": "Effects and Pedals / Distortion",
          "seller": "Telecasters",
          "sellerRating": null,
          "sellerFeedbackCount": null,
          "offersEnabled": true,
          "quantity": 1,
          "shippingPrice": {
            "amount": 11.88,
            "currency": "USD"
          },
          "shippingEstimated": true,
          "createdAt": "2026-09-14T18:53:59-05:00",
          "publishedAt": "2026-09-14T18:55:56-05:00"
        }
      }
    ]
  }
}

Responses

Status

Meaning

200

The reverb search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.query

string

—

data.page

integer

—

data.total_results

integer or null

—

data.next_page

integer or null

Send as page for the next page; null on the last one.

data.next_cursor

string or null

Poshmark only: send as cursor for the next page; null on the last one.

data.results

object[]

—

GitHub search.

Repositories, users or issues matching a query, with GitHub's own search qualifiers (language:go, stars:>1000, repo:owner/name is:open): stars, forks, topics, followers, comments and more. Up to 100 per page; a search reaches its first 1,000 results.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

type

string

—

What to search for. issues includes pull requests (is_pull_request). One of: repositories, users, issues. Default repositories.

query

string

yes

The search terms and qualifiers, e.g. web scraper language:go stars:>500.

sort

string

—

Repositories: stars, forks, help-wanted-issues, updated. Users: followers, repositories, joined. Issues: comments, reactions, created, updated. Leave out for best match.

order

string

—

With sort: the direction. One of: desc, asc. Default desc.

limit

integer

—

Results per page, 1–100. Default 30.

page

integer

—

Page number; page × limit can be at most 1000. Default 1.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/github/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d type=repositories \
  --data-urlencode "query=web scraper language:go" \
  -d sort=stars

Response

{
  "endpoint": "github/search",
  "url": "https://github.com/search?q=web+scraper+language%3Ago&type=repositories",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "type": "repositories",
    "query": "web scraper language:go",
    "sort": "stars",
    "order": "desc",
    "page": 1,
    "total_results": 1377,
    "results": [
      {
        "id": 138322040,
        "name": "go-rod/rod",
        "owner": "go-rod",
        "url": "https://github.com/go-rod/rod",
        "description": "A Chrome DevTools Protocol driver for web automation and scraping.",
        "homepage": "https://go-rod.github.io",
        "language": "Go",
        "stars": 7145,
        "forks": 400,
        "open_issues": 100,
        "license": "MIT",
        "topics": ["automation", "scraping"],
        "archived": false,
        "fork": false,
        "created_at": "2018-06-22T07:12:51Z",
        "updated_at": "2026-11-05T08:00:00Z",
        "pushed_at": "2026-11-01T10:00:00Z"
      }
    ],
    "next_page": 2
  }
}

Responses

Status

Meaning

200

The github search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.type

string

One of: repositories, users, issues.

data.query

string

—

data.sort

string or null

—

data.order

string or null

—

data.page

integer

—

data.total_results

integer

Everything that matches; only the first 1,000 can be paged to.

data.results

any[]

—

data.next_page

integer or null

The next page; null at the end or at the 1,000-result limit.

GET /v1/structured/github/lookup

GitHub lookup.

Users and repositories by name, up to 50 per call: a login (torvalds) is a profile, owner/repo (vercel/next.js) is a repository. Followers, stars, forks, license, topics and dates.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

names

string

yes

Logins and owner/repo names, comma-separated, up to 50. A github.com link is accepted.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/github/lookup" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  --data-urlencode "names=torvalds,vercel/next.js"

Response

{
  "endpoint": "github/lookup",
  "url": "https://github.com/torvalds",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "results": [
      {
        "lookup": "torvalds",
        "kind": "user",
        "found": true,
        "id": 1024025,
        "login": "torvalds",
        "url": "https://github.com/torvalds",
        "type": "User",
        "name": "Linus Torvalds",
        "company": "Linux Foundation",
        "location": "Portland, OR",
        "blog": null,
        "bio": null,
        "followers": 330520,
        "following": 0,
        "public_repos": 12,
        "created_at": "2011-09-03T15:26:22Z"
      },
      {
        "lookup": "nobody-zz/none",
        "kind": "repository",
        "found": false
      }
    ]
  }
}

Responses

Status

Meaning

200

The github lookup as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.results

object[]

One entry per name, in the order sent. found is true (the fields follow), false (it does not exist) or null (we could not read it; retry).

Stack Exchange search.

Questions on Stack Overflow and other Stack Exchange sites matching a query and/or tags: title, score, answers, views, tags, author and dates. Up to 100 per page; page on with page.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

site

string

—

Which Stack Exchange site. One of: stackoverflow, serverfault, superuser, askubuntu, unix, softwareengineering, dba, security, stats, math, apple, webmasters. Default stackoverflow.

query

string

—

The search terms. Send this, tagged, or both.

tagged

string

—

Only questions with all of these tags, up to 5, comma-separated, e.g. python,web-scraping.

sort

string

—

Result order. One of: relevance, votes, creation, activity. Default relevance.

order

string

—

The direction. One of: desc, asc. Default desc.

limit

integer

—

Results per page, 1–100. Default 30.

page

integer

—

Page number, 1–25. Default 1.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/stackexchange/search" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d site=stackoverflow \
  --data-urlencode "query=web scraping" \
  -d sort=votes

Response

{
  "endpoint": "stackexchange/search",
  "url": "https://stackoverflow.com/search?q=web+scraping",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "site": "stackoverflow",
    "query": "web scraping",
    "tagged": [],
    "sort": "votes",
    "order": "desc",
    "page": 1,
    "results": [
      {
        "id": 450835,
        "title": "Stopping scripters from slamming your website",
        "url": "https://stackoverflow.com/questions/450835/stopping-scripters-from-slamming-your-website",
        "score": 506,
        "answers": 129,
        "views": 93898,
        "is_answered": true,
        "accepted_answer_id": 450905,
        "tags": ["security", "scripting"],
        "author": "Zack Peterson",
        "author_id": 1,
        "author_reputation": 4059,
        "created_at": "2009-01-16T14:34:00.000Z",
        "last_activity_at": "2026-10-01T09:00:00.000Z"
      }
    ],
    "next_page": 2
  }
}

Responses

Status

Meaning

200

The stack exchange search as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.site

string

—

data.query

string or null

—

data.tagged

string[]

—

data.sort

string

—

data.order

string

—

data.page

integer

—

data.results

object[]

—

data.next_page

integer or null

The next page; null at the end.

GET /v1/structured/stackexchange/questions

Stack Exchange questions.

Questions by id, up to 100 per call, each with its body as HTML: title, score, answers, views, tags, author and dates. Ids that do not exist come back in missing.

Cost: charged credits for the data it moves, like every endpoint. Also accepts POST with a JSON body.

Query parameters

Name

Type

Required

Description

site

string

—

Which Stack Exchange site. One of: stackoverflow, serverfault, superuser, askubuntu, unix, softwareengineering, dba, security, stats, math, apple, webmasters. Default stackoverflow.

ids

string

yes

Question ids, comma-separated, up to 100. A question link is accepted.

Request

curl -G "https://api.scrapelyserp.com/v1/structured/stackexchange/questions" \
  -H "Authorization: Bearer $SCRAPELY_API_KEY" \
  -d site=stackoverflow \
  --data-urlencode "ids=450835,16995184"

Response

{
  "endpoint": "stackexchange/questions",
  "url": "https://stackoverflow.com/questions/450835",
  "credits": 0.000028,
  "duration_ms": 1480,
  "data": {
    "site": "stackoverflow",
    "results": [
      {
        "id": 450835,
        "title": "Stopping scripters from slamming your website",
        "url": "https://stackoverflow.com/questions/450835/stopping-scripters-from-slamming-your-website",
        "score": 506,
        "answers": 129,
        "views": 93898,
        "is_answered": true,
        "accepted_answer_id": 450905,
        "tags": ["security", "scripting"],
        "author": "Zack Peterson",
        "author_id": 1,
        "author_reputation": 4059,
        "created_at": "2009-01-16T14:34:00.000Z",
        "last_activity_at": "2026-10-01T09:00:00.000Z",
        "body_html": "<p>I have a website that scripters are slamming…</p>"
      }
    ],
    "missing": []
  }
}

Responses

Status

Meaning

200

The stack exchange questions as JSON.

400

MISSING_PARAM or INVALID_PARAM; param names the culprit.

401

UNAUTHORIZED: missing, unknown or revoked key.

402

INSUFFICIENT_CREDITS: nothing was charged.

404

NOT_FOUND: the subreddit, post or page asked for does not exist. Not charged.

429

RATE_LIMITED or CONCURRENCY_LIMIT. Honour Retry-After.

500

INTERNAL: our fault, not charged. Quote X-Request-Id.

502

TARGET_FAILED: the retailer blocked us, errored, or timed out after retries. Not charged.

Response fields

Field

Type

Description

endpoint

string

—

url

string

The page we fetched.

credits

number

What the call was charged, in credits, fractional (also X-Scrapely-Credits): in proportion to the data its answered requests moved. Requests with no answer, blocked or errored are never charged. Small values may be written in exponent form.

duration_ms

integer

—

data

object

—

data.site

string

—

data.results

object[]

In the order the ids were sent.

data.missing

integer[]

Ids that do not exist (or were deleted).

Updated