{
  "openapi": "3.0.1",
  "info": {
    "title": "LinkedIn Jobs Scraper - Listings, Multi-Title, Location, CSV",
    "description": "LinkedIn Jobs Scraper with no login or cookies: title, company, location, posted date, full description, seniority, applicant count, Easy Apply flag, advertised pay when shown. Date/experience filters, title include/exclude, only-new-jobs monitoring, webhook alerts. CSV/JSON. $1 per 1,000 jobs.",
    "version": "0.1",
    "x-build-id": "DrbWyKeXSpaLDsi85"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/flash_scraper~linkedin-jobs-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-flash_scraper-linkedin-jobs-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/flash_scraper~linkedin-jobs-scraper/runs": {
      "post": {
        "operationId": "runs-sync-flash_scraper-linkedin-jobs-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/flash_scraper~linkedin-jobs-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-flash_scraper-linkedin-jobs-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",
        "required": [
          "searchQueries"
        ],
        "properties": {
          "searchQueries": {
            "title": "Job titles / keywords (what)",
            "type": "array",
            "description": "Job titles, skills, or company keywords to search — one per line. e.g. 'data analyst', 'react developer'.",
            "default": [
              "data analyst"
            ],
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "Location (where)",
            "type": "string",
            "description": "City, state, country, or zip to search within — e.g. 'United States', 'London', 'Remote'. Ignored when `locations` or `geoId` is set.",
            "default": "United States"
          },
          "locations": {
            "title": "Locations (one search per place)",
            "type": "array",
            "description": "Optional. Search each of these places separately INSTEAD of `location` — e.g. 'Austin, TX', 'Dallas, TX', 'Houston, TX'. LinkedIn's public search stops at 800 results per search, so a list of cities is how one run goes past that wall for a whole state or country; a posting found under two places is delivered (and billed) once. `maxItems` applies to EACH place. Up to 25 places per run — extra entries are not searched and the run says so. Leave empty to search `location`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "geoId": {
            "title": "LinkedIn geoId (optional)",
            "type": "string",
            "description": "Optional. The numeric geoId from a LinkedIn job-search URL (the number after geoId=, e.g. 103644278 = United States). When set, `location` and `locations` are ignored and LinkedIn's own place id pins the search, so ambiguous names (Paris, Cambridge, Georgia) resolve deterministically. Measured 2026-08-29 from a home IP: geoId=103644278 with no location returned the same listings as location 'United States'. A non-numeric value is ignored (the run says so) and `location` is used."
          },
          "datePosted": {
            "title": "Date posted",
            "enum": [
              "",
              "r86400",
              "r604800",
              "r2592000"
            ],
            "type": "string",
            "description": "Only jobs posted within this window.",
            "default": ""
          },
          "experienceLevel": {
            "title": "Experience level",
            "type": "array",
            "description": "Keep only jobs at these seniority levels (leave empty for all). Checked on each job page's own 'Seniority level' (or, when the poster set none, on clear title words like Senior, Director or Junior): a job at another level, or whose page could not be read, is left out and not billed; a job with no level anywhere is kept.",
            "items": {
              "type": "string",
              "enum": [
                "1",
                "2",
                "3",
                "4",
                "5"
              ],
              "enumTitles": [
                "Internship",
                "Entry level",
                "Associate",
                "Mid-Senior level",
                "Director"
              ]
            },
            "default": []
          },
          "contractType": {
            "title": "Employment type",
            "type": "array",
            "description": "Employment type HINT (leave empty for all). Since LinkedIn's August 2026 AI search (measured 2026-08-29) workplace type and job type are not honoured at the source; the actor converts them to search keywords plus a title/location check — verify with isRemote. Each code is appended to the search as a word (Part-time → 'part-time', Contract → 'contract', Temporary → 'temporary', Internship → 'internship'); Full-time adds no keyword (LinkedIn's default — verify with employmentType); the row's employmentType column, read from the job page, is the truth.",
            "items": {
              "type": "string",
              "enum": [
                "F",
                "P",
                "C",
                "T",
                "I"
              ],
              "enumTitles": [
                "Full-time",
                "Part-time",
                "Contract",
                "Temporary",
                "Internship"
              ]
            },
            "default": []
          },
          "remote": {
            "title": "Work arrangement",
            "type": "array",
            "description": "Work arrangement HINT (leave empty for all). Since LinkedIn's August 2026 AI search (measured 2026-08-29) workplace type and job type are not honoured at the source; the actor converts them to search keywords plus a title/location check — verify with isRemote. Codes become search words ('remote' / 'hybrid'); On-site adds no keyword (LinkedIn's default — verify with isRemote). Remote only (just '2') additionally keeps only listings whose title or location says remote/WFH — checked on the search cards BEFORE the job pages are read, so the others are neither fetched nor billed.",
            "items": {
              "type": "string",
              "enum": [
                "1",
                "2",
                "3"
              ],
              "enumTitles": [
                "On-site",
                "Remote",
                "Hybrid"
              ]
            },
            "default": []
          },
          "companyNames": {
            "title": "Companies",
            "type": "array",
            "description": "Keep only listings whose company name, as printed on the search card, contains one of these (case-insensitive substring: 'Google' keeps Google and Google Cloud, drops Alphabet). Checked on the search cards BEFORE the job pages are read, so a dropped listing is neither fetched nor billed. A subsidiary or a differently spelled legal name is dropped — use `companyId` for an exact pin. Leave empty for all.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "companyId": {
            "title": "Company IDs",
            "type": "array",
            "description": "Filter by LinkedIn numeric company IDs (from a company page URL). Leave empty for all.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Max jobs per search",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Maximum number of jobs per search (1-1000): per search query and, when `locations` is set, per place — 3 queries x 4 places can deliver up to 12 x this figure (a posting found under two places is billed once).",
            "default": 100
          },
          "requireSalary": {
            "title": "Only jobs with a salary",
            "type": "boolean",
            "description": "Keep only listings whose public job page shows a base-pay range (varies by posting and state; on the 6 pages measured 2026-08-29, 2 showed a base-pay range). Listings without advertised pay — and listings whose job page could not be read — are dropped.",
            "default": false
          },
          "minSalary": {
            "title": "Minimum salary (annualized)",
            "minimum": 0,
            "type": "integer",
            "description": "Keep only listings whose advertised pay (salaryMax, else salaryMin) is at least this much per year; hourly pay is annualized (x2080). Listings showing no pay are dropped, like requireSalary. 0 = no filter.",
            "default": 0
          },
          "easyApplyOnly": {
            "title": "Easy Apply only",
            "type": "boolean",
            "description": "Keep only jobs that support LinkedIn Easy Apply — applied at the source (measured 2026-08-29 from a home IP; the post-fetch check stays as a safety net), so the run asks LinkedIn for Easy Apply postings instead of reading every job page to find them.",
            "default": false
          },
          "maxApplicants": {
            "title": "Max applicants",
            "minimum": 0,
            "type": "integer",
            "description": "Keep only jobs with at most this many applicants (low-competition roles; 0 = no filter).",
            "default": 0
          },
          "titleInclude": {
            "title": "Title must contain (any of)",
            "type": "array",
            "description": "Keep only listings whose job title contains at least one of these words or phrases (case-insensitive). Checked on the search cards BEFORE the job pages are read, so a dropped listing is neither fetched nor billed. Leave empty for all.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "titleExclude": {
            "title": "Title must not contain",
            "type": "array",
            "description": "Drop listings whose job title contains any of these words or phrases (case-insensitive) — e.g. 'intern', 'manager', 'clearance'. Checked on the search cards BEFORE the job pages are read, so a dropped listing is neither fetched nor billed. Leave empty for none.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "excludeAgencies": {
            "title": "Exclude staffing agencies",
            "type": "boolean",
            "description": "Drop listings whose company name looks like a staffing / recruiting agency (name contains staffing, recruit, talent, headhunt, manpower, personnel, placement, consultancy, resourcing, workforce, ...). A name-based heuristic: 'Deloitte Consulting' passes, 'TalentBridge Staffing' is dropped. Checked on the search cards BEFORE the job pages are read, so a dropped listing is neither fetched nor billed.",
            "default": false
          },
          "onlyNewJobs": {
            "title": "Only new jobs (monitor mode)",
            "type": "boolean",
            "description": "ON: the run remembers every listing it delivers for this exact search (queries + location + filters) in a key-value store in YOUR account and, on later runs, delivers — and bills — only listings that are new since. The first run is the baseline. A quiet run delivers nothing and charges nothing. OFF (default): every run returns everything it finds.",
            "default": false
          },
          "descriptionFormat": {
            "title": "Description format",
            "enum": [
              "text",
              "markdown",
              "html"
            ],
            "type": "string",
            "description": "How the posting's description is written into the `descriptionText` column. `text` (default): plain text, whitespace collapsed — unchanged. `markdown`: **bold**, *italic*, `- ` bullets, `1.` numbers, `[text](url)` links and line breaks from the job page's own markup — the best input for an LLM or a spreadsheet. `html`: the description block as LinkedIn serves it (<strong>, <em>, <br>, <ul>/<li>, <p>, <a>; Angular comment markers removed). Same request, same page, no extra fetch and no price change; the column keeps its name and position, and job_score is computed from the plain text in every format.",
            "default": "text"
          },
          "proxyConfiguration": {
            "title": "Proxy (optional)",
            "type": "object",
            "description": "Optional. Leave empty and every request goes straight from the Apify container, which LinkedIn's public job search answers today. Set a proxy (Apify RESIDENTIAL, a country, or your own proxy URLs) when LinkedIn gates your region with sign-in pages or HTTP 999, or on heavy schedules: each connection then gets its own proxy session, and every retry after a block or a network error moves to a NEW session (a fresh exit IP) instead of re-hitting the same address. Proxy traffic is billed by Apify on top of the per-result price."
          },
          "webhookUrl": {
            "title": "Alert webhook URL (Slack, Discord, n8n, Make, Zapier…)",
            "type": "string",
            "description": "Optional. When at least one row is delivered, the run POSTs a digest to this URL: a Slack incoming webhook gets a text message, a Discord webhook gets a message, any other URL (n8n / Make / Zapier catch hook, your own endpoint) gets JSON with the counts, console links and the first 20 rows. Quiet runs send nothing. Pair it with onlyNewJobs on a schedule and this actor becomes an alert service on its own. Delivery is best-effort: a webhook failure is reported in the status message and never fails the run."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}