{
  "openapi": "3.0.1",
  "info": {
    "title": "TikTok Shop Scraper - Products, Prices, Sales & Reviews (US)",
    "description": "Search TikTok Shop US by keyword or paste product links for public product data: title, price and original price, discount, units sold, rating, review count, shop, images and URL - plus the product page's public reviews. No login, no cookies. Anything cut short is labelled, never reported as zero.",
    "version": "0.2",
    "x-build-id": "Sc3ZYaxLRwKewOZzW"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/lanternlab318~tiktok-shop/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-lanternlab318-tiktok-shop",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/lanternlab318~tiktok-shop/runs": {
      "post": {
        "operationId": "runs-sync-lanternlab318-tiktok-shop",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/lanternlab318~tiktok-shop/run-sync": {
      "post": {
        "operationId": "run-sync-lanternlab318-tiktok-shop",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "searchQueries": {
            "title": "Keywords",
            "type": "array",
            "description": "One TikTok Shop keyword per line: \"coffee grinder\", \"yoga mat\", \"air fryer\". Each keyword is looked up separately and every product row says which keyword found it. TikTok Shop's public search page serves one page of results per keyword and offers no way to page past it, so a keyword returns at most 30 products however high you set maxProducts - and because it sometimes renders that page with only 5 results while claiming to be complete, the Actor asks again from a new IP while the page comes back short and keeps the largest rendering. A product found by several keywords is written and charged once.",
            "items": {
              "type": "string"
            }
          },
          "productUrls": {
            "title": "Product links",
            "type": "array",
            "description": "One TikTok Shop product page per line: \"https://www.tiktok.com/shop/pdp/<slug>/<product-id>\". A \"https://shop.tiktok.com/us/pdp/...\" link, a link without the slug or the bare product ID also work. Each link is read from the product's own page, which carries more than the search list does: every product image, the stock state and the shop's rating.",
            "items": {
              "type": "string"
            }
          },
          "region": {
            "title": "TikTok Shop region",
            "enum": [
              "US"
            ],
            "type": "string",
            "description": "Which TikTok Shop storefront to read. Only the United States storefront is supported in this version; other regions are refused up front rather than returning a US catalogue under the wrong label.",
            "default": "US"
          },
          "maxProducts": {
            "title": "Max products per keyword",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "Upper bound on the product rows one keyword may produce. It applies per keyword, not to the whole run: three keywords at 30 can return 90 products. Product links are not affected - every link you give is read. TikTok Shop's own page limit is 30 products per keyword, so a higher number cannot return more and the keyword is marked partial when it is reached.",
            "default": 30
          },
          "includeReviews": {
            "title": "Also collect reviews",
            "type": "boolean",
            "description": "Collect the reviews TikTok Shop shows on the public product page as well. Off by default, because it costs one extra request per product. The product page shows only its first screen of reviews - at most 5 - and offers no public way to page past them, so a product with more reviews than that gets a review status row saying how many of how many arrived. Only what the page shows publicly is collected: rating, text, post date, country, whether it is a verified purchase, the review's own photos, and the display name TikTok Shop itself publishes already masked (\"L**\"). The reviewer's account ID and avatar are not collected.",
            "default": false
          },
          "maxReviewsPerProduct": {
            "title": "Max reviews per product",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Upper bound on the review rows one product may produce. TikTok Shop's public product page serves at most 5 reviews, so a higher number cannot return more.",
            "default": 5
          },
          "maxUpstreamRequests": {
            "title": "Max TikTok Shop requests",
            "minimum": 1,
            "type": "integer",
            "description": "Hard ceiling on the HTTP requests this run sends to TikTok Shop: keyword searches, product pages and review pages together, retries included. At the ceiling collection stops - the inputs not reached are written with partialReason \"upstream_request_cap\" and the run then ends normally. Leave empty and the Actor works a ceiling out from your keywords, links, maxProducts and includeReviews, so a run is never unbounded."
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Where the requests to TikTok Shop come from. The default (Apify Proxy, datacenter) is the cheapest and is what this Actor is measured on. TikTok Shop answers an occasional request with a security check instead of the page; every retry leaves from a new IP, and a request that keeps being refused is reported as blocked rather than as an empty result. Switch to residential if your run sees many security checks.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}