{
  "openapi": "3.0.1",
  "info": {
    "title": "Twitter Scraper & API (X.com): Tweets, Posts, Search",
    "description": "Scrape X (Twitter) tweets and posts by keyword, hashtag, profile, list, URL or thread. No X API key. JSON or CSV with text, author, engagement and media. $0.49 per 1,000 tweets, down to $0.46 with a Store discount; $0 for empty results. API, Python and MCP. Unofficial, not affiliated with X Corp.",
    "version": "1.0",
    "x-build-id": "GNfp4RgRowlkpmOp8"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/codeperfection~x-twitter-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-codeperfection-x-twitter-scraper",
        "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/codeperfection~x-twitter-scraper/runs": {
      "post": {
        "operationId": "runs-sync-codeperfection-x-twitter-scraper",
        "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/codeperfection~x-twitter-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-codeperfection-x-twitter-scraper",
        "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": {
          "searchTerms": {
            "title": "Search terms (keywords, hashtags, X operators)",
            "type": "array",
            "description": "One or more searches to run. Each term supports full X advanced-search syntax (for example \"web scraping\", \"#ai\", \"apify lang:en\"). Terms are paginated independently, and results are deduplicated by tweet ID across all terms, so you are not charged for the same tweet twice in a run. Provide at least one of: searchTerms, twitterHandles, startUrls, or conversationIds.",
            "items": {
              "type": "string",
              "minLength": 1
            }
          },
          "twitterHandles": {
            "title": "Profiles (X handles)",
            "type": "array",
            "description": "Scrape tweets authored by these accounts (handle without the @). Each handle runs as a from: search, so your date, engagement, and language filters still apply. Deduplicated with everything else in the run.",
            "items": {
              "type": "string",
              "minLength": 1
            }
          },
          "startUrls": {
            "title": "X URLs (tweet, profile, search, list, hashtag)",
            "type": "array",
            "description": "Scrape directly from X URLs. Supported: a tweet URL (x.com/user/status/ID for that exact tweet), a profile URL (x.com/user for that user's tweets), a search URL (x.com/search?q=... for that query), a list URL (x.com/i/lists/ID), or a hashtag URL (x.com/hashtag/tag). An unrecognized URL is recorded in the run's SKIPPED_SEEDS record and not charged."
          },
          "conversationIds": {
            "title": "Replies to a tweet (conversation IDs)",
            "type": "array",
            "description": "Expand one or more X threads. Give a conversation ID (the thread root tweet's ID) to get the replies in that conversation. Your filters still apply, and replies are deduplicated across the run like everything else.",
            "items": {
              "type": "string"
            }
          },
          "sort": {
            "title": "Sort order",
            "enum": [
              "Latest",
              "Top"
            ],
            "type": "string",
            "description": "\"Latest\" is reverse-chronological (newest first). \"Top\" is X's relevance ranking.",
            "default": "Latest"
          },
          "maxTweets": {
            "title": "Max tweets per search term",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "Hard cap on real tweets returned per search term. You are charged only for the real tweets delivered, so a search that finds fewer than this (or none) costs proportionally less (or nothing).",
            "default": 100
          },
          "maxTotalTweets": {
            "title": "Max tweets for the whole run",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "Optional global cap on real tweets delivered across all search terms combined (maxTweets is the per-term cap). The run stops once this total is reached. Leave empty for no global cap."
          },
          "startDate": {
            "title": "Start date",
            "type": "string",
            "description": "Only tweets at or after this date (UTC). Accepts an absolute date (YYYY-MM-DD or ISO-8601 timestamp) or a relative value like \"7 days\" or \"1 month\". Applied server-side and re-checked on every returned tweet."
          },
          "endDate": {
            "title": "End date (exclusive)",
            "type": "string",
            "description": "Only tweets strictly before this date (UTC). Accepts an absolute date (YYYY-MM-DD or ISO-8601 timestamp) or a relative value like \"1 day\"."
          },
          "fromUser": {
            "title": "Only tweets from this account",
            "type": "string",
            "description": "Only tweets authored by this account (handle without the @). Applied server-side (from:) and re-checked against the tweet author."
          },
          "toUser": {
            "title": "Only replies to this account",
            "type": "string",
            "description": "Only tweets that are a direct reply to this account (handle without the @). Matches the reply target, not arbitrary mentions."
          },
          "minFaves": {
            "title": "Minimum likes",
            "minimum": 0,
            "type": "integer",
            "description": "Only tweets with at least this many likes."
          },
          "minRetweets": {
            "title": "Minimum retweets",
            "minimum": 0,
            "type": "integer",
            "description": "Only tweets with at least this many retweets."
          },
          "minReplies": {
            "title": "Minimum replies",
            "minimum": 0,
            "type": "integer",
            "description": "Only tweets with at least this many replies."
          },
          "language": {
            "title": "Language (code, e.g. en)",
            "pattern": "^\\s*([A-Za-z]{2,3}(-[A-Za-z]{2,4})?)?\\s*$",
            "type": "string",
            "description": "Only tweets in this language, as an ISO 639-1 code (for example en, ru, es, de). A tweet with no detected language is dropped rather than returned."
          },
          "media": {
            "title": "Media type",
            "enum": [
              "",
              "any",
              "images",
              "videos"
            ],
            "type": "string",
            "description": "Restrict to tweets that carry media of the chosen kind.",
            "default": ""
          },
          "onlyVerified": {
            "title": "Verified authors only",
            "type": "boolean",
            "description": "Only tweets from verified accounts (legacy verified or X Premium/blue).",
            "default": false
          },
          "onlyBlueVerified": {
            "title": "X Premium (blue) authors only",
            "type": "boolean",
            "description": "Only tweets from X Premium (blue) accounts. Stricter than 'Verified authors only'.",
            "default": false
          },
          "onlyQuote": {
            "title": "Quote tweets only",
            "type": "boolean",
            "description": "Only quote tweets (a tweet that embeds another tweet). Applied with filter:quote and re-checked on every returned tweet.",
            "default": false
          },
          "mentioning": {
            "title": "Only tweets mentioning this account",
            "type": "string",
            "description": "Only tweets that mention this account (handle without the @). Applied server-side and re-checked against each tweet's mentions."
          },
          "includeSearchTerms": {
            "title": "Tag each tweet with its search term",
            "type": "boolean",
            "description": "Add a `search_term` field to every tweet recording which of your search terms found it. Useful when running several terms in one run.",
            "default": false
          },
          "outputPreset": {
            "title": "Output format",
            "enum": [
              "full",
              "compact",
              "csvFlat"
            ],
            "type": "string",
            "description": "The base shape of every delivered tweet, before any advanced transform. \"Full\" is the complete nested JSON (all fields). \"Compact\" is a lean high-value JSON subset (author kept nested). \"CSV flat\" is flat scalar columns for CSV and spreadsheet tools (author flattened, arrays joined; structurally flat, but not formula-injection-sanitized, so see the docs if you import into a formula-evaluating app). One item out per tweet: the preset never changes how many tweets you get or what you are charged.",
            "default": "full"
          },
          "flattenAuthor": {
            "title": "Flatten author into columns (for CSV/Excel)",
            "type": "boolean",
            "description": "Legacy shortcut: replace the nested `author` object with flat `author_*` columns (author_followers, author_verified, ...). Applies to the Full and Compact presets; the CSV flat preset already flattens the author. Leave off to keep the nested JSON shape.",
            "default": false
          },
          "transformMode": {
            "title": "Reshape mode",
            "enum": [
              "none",
              "projection",
              "jq"
            ],
            "type": "string",
            "description": "Optional advanced step applied on top of the format. \"None\" delivers the format unchanged. \"Pick the fields you want\" lets you choose, order, rename, and flatten fields and add constant columns without code. \"Custom formula (jq)\" runs an advanced jq program for calculated and derived fields (sums, ratios, conditionals). None of them can change the number of items: every accepted tweet still produces exactly one output item. Settings for the inactive modes are checked for validity but not applied.",
            "default": "none"
          },
          "projection": {
            "title": "Field picker (used when Reshape mode is 'Pick the fields you want')",
            "type": "object",
            "description": "Choose, order, rename, flatten, and add string constants without changing the number of output items. Ignored unless Reshape mode is 'Pick the fields you want'.",
            "properties": {
              "selection": {
                "title": "Field selection",
                "type": "string",
                "description": "Output only the listed fields (plus constants), or keep all preset fields while applying the listed renames and promotions.",
                "editor": "select",
                "enum": [
                  "onlyListed",
                  "allFields"
                ],
                "enumTitles": [
                  "Only listed fields",
                  "All fields, with listed overrides"
                ],
                "default": "onlyListed"
              },
              "fields": {
                "title": "Fields",
                "type": "array",
                "description": "Ordered source paths to select or rename, as JSON: a list of {\"from\",\"to\"} objects. `from` is a documented field or dotted object path (for example author.username); a blank or omitted `to` uses the final path segment. Example: [{\"from\":\"author.username\",\"to\":\"handle\"}]",
                "editor": "json",
                "default": [],
                "maxItems": 200,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "from"
                  ],
                  "properties": {
                    "from": {
                      "title": "Source path",
                      "type": "string",
                      "description": "Documented preset field or dotted object path, for example author.username.",
                      "editor": "textfield"
                    },
                    "to": {
                      "title": "Output name",
                      "type": "string",
                      "description": "Optional literal top-level output key; blank uses the final source-path segment.",
                      "editor": "textfield",
                      "default": ""
                    }
                  }
                }
              },
              "flatten": {
                "title": "Flatten nested objects",
                "type": "boolean",
                "description": "Recursively flatten remaining nested objects into dot-named keys; arrays are not expanded into rows.",
                "editor": "checkbox",
                "default": false
              },
              "constants": {
                "title": "String constants",
                "type": "array",
                "description": "Add constant string columns such as run tags. Keys must be unique and cannot overwrite a projected field.",
                "editor": "keyValue",
                "default": [],
                "maxItems": 100,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "key",
                    "value"
                  ],
                  "properties": {
                    "key": {
                      "type": "string",
                      "title": "Output name",
                      "description": "Top-level output key for this constant column."
                    },
                    "value": {
                      "type": "string",
                      "title": "Value",
                      "description": "Constant string value placed in that column on every row."
                    }
                  }
                }
              },
              "arrays": {
                "title": "Array handling",
                "type": "string",
                "description": "How to handle top-level array fields: keep them as JSON arrays, encode them as compact JSON strings, or join their values into one string (nested arrays inside kept objects are unaffected).",
                "editor": "select",
                "enum": [
                  "keep",
                  "json",
                  "join"
                ],
                "enumTitles": [
                  "Keep arrays",
                  "JSON-encode arrays",
                  "Join array values"
                ],
                "default": "keep"
              },
              "arrayJoinSeparator": {
                "title": "Array join separator",
                "type": "string",
                "description": "Separator used when array handling is Join; ignored otherwise.",
                "editor": "textfield",
                "default": ","
              },
              "missingFields": {
                "title": "Missing optional fields",
                "type": "string",
                "description": "Omit a listed field that is absent from a tweet, or emit it with a null value.",
                "editor": "select",
                "enum": [
                  "omit",
                  "null"
                ],
                "enumTitles": [
                  "Omit the field",
                  "Output null"
                ],
                "default": "omit"
              }
            },
            "default": {
              "selection": "onlyListed",
              "fields": [],
              "flatten": false,
              "constants": [],
              "arrays": "keep",
              "arrayJoinSeparator": ",",
              "missingFields": "omit"
            },
            "additionalProperties": false
          },
          "jqExpression": {
            "title": "jq expression (jq mode only)",
            "type": "string",
            "description": "An advanced jq expression that reshapes each tweet into exactly one output object, for calculated and derived fields (engagement sums, ratios, conditionals, renames) beyond what the field picker can express. It runs on the preset-shaped tweet and must return exactly one JSON object per tweet: it cannot filter, drop, or fan out. An expression that returns nothing, a scalar, null, or multiple values is rejected before any paid run (a free dry-run is available). Module loading and environment or extra-input builtins are not permitted. Ignored unless Reshape mode is jq. Example: {id, text, engagement: (.like_count + .retweet_count + .reply_count)}",
            "default": "."
          },
          "jqVariables": {
            "title": "jq variables (jq mode only)",
            "maxItems": 50,
            "type": "array",
            "description": "Optional string variables passed to the jq expression as $name (for example a campaign tag reused across the expression). Ignored unless Reshape mode is jq.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "key",
                "value"
              ],
              "properties": {
                "key": {
                  "type": "string",
                  "title": "Variable name",
                  "description": "Variable name, referenced in the jq expression as $name."
                },
                "value": {
                  "type": "string",
                  "title": "Value",
                  "description": "String value bound to the variable for this run."
                }
              }
            },
            "default": []
          },
          "outputCardinality": {
            "title": "Output cardinality",
            "enum": [
              "oneToOne"
            ],
            "type": "string",
            "description": "Contract guarantee: exactly one dataset item is produced for each delivered unique tweet. Only \"oneToOne\" is supported.",
            "default": "oneToOne"
          },
          "validateTransformOnly": {
            "title": "Preview output shape only (free, no scrape)",
            "type": "boolean",
            "description": "Validate the selected preset and transform against a fixed canonical sample tweet and write a preview to the run's Output, with no scrape, no dataset items, and no charge. Use it to check your transform before a paid run.",
            "default": false
          },
          "placeObjectId": {
            "title": "Place ID (not supported)",
            "pattern": "^$",
            "type": "string",
            "description": "Accepted only when empty, for compatibility with inputs copied from other X scrapers. No available data source returns the place ID needed to verify a place match, so a value is rejected."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}