{
  "data": {
    "id": "UDvxBZWkemautfC7a",
    "actId": "1UqwHluTBCEfxhsnE",
    "userId": "XQ4b5NlpHfNjEMtso",
    "startedAt": "2026-10-17T14:48:19.904Z",
    "finishedAt": "2026-10-17T14:48:22.556Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 2584,
      "runTimeSecs": 2.584,
      "computeUnits": 0.002871111111111111,
      "imageSizeBytes": 342692864
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"LinkedIn Job Scraper Input\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"searchQueries\": {\n      \"title\": \"Search queries\",\n      \"type\": \"array\",\n      \"description\": \"Keywords or job titles to search for (e.g. 'Python Developer', 'Data Scientist'). Each query produces a separate search.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": [\n        \"Python Developer\"\n      ]\n    },\n    \"startUrls\": {\n      \"title\": \"Start URLs\",\n      \"type\": \"array\",\n      \"description\": \"Direct LinkedIn job search URLs. Overrides searchQueries when provided.\",\n      \"editor\": \"requestListSources\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"locations\": {\n      \"title\": \"Locations\",\n      \"type\": \"array\",\n      \"description\": \"Location names to filter jobs (e.g. 'Germany', 'United States', 'London'). Applied to all search queries.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"timeRange\": {\n      \"title\": \"Time range\",\n      \"type\": \"string\",\n      \"description\": \"Filter jobs by posting date.\",\n      \"enum\": [\n        \"any\",\n        \"past24Hours\",\n        \"pastWeek\",\n        \"pastMonth\"\n      ],\n      \"enumTitles\": [\n        \"Any time\",\n        \"Past 24 hours\",\n        \"Past week\",\n        \"Past month\"\n      ],\n      \"default\": \"any\"\n    },\n    \"jobType\": {\n      \"title\": \"Job type\",\n      \"type\": \"array\",\n      \"description\": \"Filter by employment type. Leave empty for all types.\",\n      \"editor\": \"select\",\n      \"default\": [],\n      \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"fullTime\",\n          \"partTime\",\n          \"contract\",\n          \"temporary\",\n          \"internship\",\n          \"volunteer\"\n        ],\n        \"enumTitles\": [\n          \"Full-time\",\n          \"Part-time\",\n          \"Contract\",\n          \"Temporary\",\n          \"Internship\",\n          \"Volunteer\"\n        ]\n      }\n    },\n    \"experienceLevel\": {\n      \"title\": \"Experience level\",\n      \"type\": \"array\",\n      \"description\": \"Filter by required experience level. Leave empty for all levels.\",\n      \"editor\": \"select\",\n      \"default\": [],\n      \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"internship\",\n          \"entryLevel\",\n          \"associate\",\n          \"midSenior\",\n          \"director\",\n          \"executive\"\n        ],\n        \"enumTitles\": [\n          \"Internship\",\n          \"Entry level\",\n          \"Associate\",\n          \"Mid-senior level\",\n          \"Director\",\n          \"Executive\"\n        ]\n      }\n    },\n    \"remote\": {\n      \"title\": \"Remote / Work type\",\n      \"type\": \"array\",\n      \"description\": \"Filter by work arrangement. Leave empty for all types.\",\n      \"editor\": \"select\",\n      \"default\": [],\n      \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"onSite\",\n          \"remote\",\n          \"hybrid\"\n        ],\n        \"enumTitles\": [\n          \"On-site\",\n          \"Remote\",\n          \"Hybrid\"\n        ]\n      }\n    },\n    \"maxItems\": {\n      \"title\": \"Max items\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum number of job postings to scrape. 0 = unlimited.\",\n      \"default\": 0,\n      \"minimum\": 0,\n      \"prefill\": 10\n    },\n    \"extractCompanyDetails\": {\n      \"title\": \"Extract company details\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, also scrapes each company's LinkedIn page for full company details (description, followers, specialties, etc.) and appends them to the output.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"maxConcurrency\": {\n      \"title\": \"Max concurrency\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum number of parallel detail page fetches. Higher values increase speed but may trigger rate limiting. Recommended: 3-10.\",\n      \"default\": 5,\n      \"minimum\": 1,\n      \"maximum\": 20,\n      \"prefill\": 5\n    },\n    \"proxyConfiguration\": {\n      \"title\": \"Proxy configuration\",\n      \"type\": \"object\",\n      \"description\": \"Proxy settings for anti-bot protection.\",\n      \"editor\": \"proxy\",\n      \"default\": {\n        \"useApifyProxy\": true,\n        \"apifyProxyGroups\": [\n          \"RESIDENTIAL\"\n        ]\n      }\n    }\n  },\n  \"required\": []\n}",
    "readme": "**LinkedIn Job Scraper** creates a structured dataset of job postings collected from [LinkedIn](https://www.linkedin.com). Each dataset item represents one LinkedIn job and can include identifiers, title, description, posting dates, employment type, company name and URL, location fields, coordinates, industry, skills, experience, and education. Query the source with keyword searches (`searchQueries`) plus locations and filters, or with LinkedIn job search URLs in `startUrls` (these override `searchQueries` when provided). Control the result limit with `maxItems`, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, XML, or another supported format.\n\n## Dataset at a glance\n\n| Property | Value |\n|---|---|\n| Source | linkedin.com (public job listings) |\n| Record unit | One LinkedIn job |\n| Input methods | Keyword search (`searchQueries`) plus `locations` and filters, or LinkedIn job search URLs (`startUrls`) |\n| Main identifiers | `jobId`, `url` |\n| Delivery | Apify Dataset and API |\n| Export formats | JSON, CSV, Excel, XML, HTML (Apify dataset exports) |\n| Update model | Fresh records per Actor run |\n| Pricing | $0.00005 per Actor start; $0.001 per job ($1 per 1,000 jobs) |\n\n## Coverage and available records\n\nThe Actor collects public LinkedIn job listings using one of two entry points:\n\n- **Search-based**: Set `searchQueries` to job titles or keywords (for example `Python Developer`). Each query is a separate search. `locations` applies to every query. Filters (`timeRange`, `jobType`, `experienceLevel`, `remote`) narrow the search.\n- **URL-based**: Pass LinkedIn job search URLs in `startUrls`. When `startUrls` is provided, `searchQueries` is ignored.\n\nRecord types and limits:\n\n- **Job records** are always collected: `jobId`, title, description, dates, employment type, company name and URL, location fields, coordinates, industry, skills, experience, education, and the job URL.\n- **Company page fields** are conditional: they attach onto the same job record only when `extractCompanyDetails` is enabled. They are not a separate dataset item.\n- **Result cap**: `maxItems` limits the number of jobs collected (`0` means unlimited, the default; Console prefill is `10`).\n\nKnown exclusions: content LinkedIn only shows behind login is not collected; each run captures listing state at run time (no historical snapshots); company page fields are omitted when `extractCompanyDetails` is off or the company page is unavailable.\n\n## Data dictionary\n\nField names below match dataset record JSON properties exactly. `jobId` is the recommended deduplication key; `url` is a reasonable secondary key. Dates are ISO 8601 timestamps as returned on the listing (for example `2026-05-08T13:38:46.000Z`). `country` is a country code. `latitude` and `longitude` are decimal degrees when present.\n\n| Field | Type | Nullable | Description | Example |\n|---|---|---:|---|---|\n| `jobId` | string | No | LinkedIn job identifier; best stable deduplication key | `4412111373` |\n| `title` | string | No | Job title | `Python Developer` |\n| `description` | string | Yes | Full job description text | See example record |\n| `datePosted` | string | Yes | Posting timestamp (ISO 8601) | `2026-05-08T13:38:46.000Z` |\n| `validThrough` | string | Yes | Listing end timestamp (ISO 8601) | `2026-11-04T13:38:46.000Z` |\n| `employmentType` | string | Yes | Employment type as shown on the listing | `FULL_TIME` |\n| `companyName` | string | Yes | Hiring company name | `DATAGROUP` |\n| `companyUrl` | string | Yes | LinkedIn company page URL | `https://de.linkedin.com/company/datagroup-se` |\n| `companyLogo` | string | Yes | Company logo image URL | See example record |\n| `country` | string | Yes | Country code | `DE` |\n| `city` | string | Yes | City as shown on the listing | `Krakau` |\n| `latitude` | number | Yes | Location latitude in decimal degrees | `51.36391` |\n| `longitude` | number | Yes | Location longitude in decimal degrees | `11.857489` |\n| `industry` | string | Yes | Industry text as shown on the listing | `IT-Dienstleistungen und IT-Beratung` |\n| `skills` | string | Yes | Skills text; empty when the listing does not provide it | `\"\"` |\n| `monthsOfExperience` | string | Yes | Experience requirement as returned on the listing; empty when not provided | `\"\"` |\n| `educationLevel` | string | Yes | Education requirement as shown on the listing | `bachelor degree` |\n| `url` | string | No | Job posting URL; secondary deduplication key | `https://de.linkedin.com/jobs/view/python-developer-at-datagroup-4412111373` |\n| `location` | string | Yes | Full location string (city, region, country) | `Krakau, Saxony-Anhalt, Germany` |\n\nWhen `extractCompanyDetails` is true, company page fields attach onto this same job record. They are omitted when the toggle is off.\n\n## Example dataset record\n\nReal record produced with the test input below (`searchQueries`: `Python Developer`, `locations`: `Germany`, `maxItems`: `10`). The `description` text is shortened for readability; the live record contains the full listing copy.\n\n```json\n{\n  \"jobId\": \"4412111373\",\n  \"title\": \"Python Developer\",\n  \"description\": \"Job Description DATAGROUP Polska. Design and implement robust, scalable, and efficient JAVA-based frontend as well as Python components for the ETL process.\",\n  \"datePosted\": \"2026-05-08T13:38:46.000Z\",\n  \"validThrough\": \"2026-11-04T13:38:46.000Z\",\n  \"employmentType\": \"FULL_TIME\",\n  \"companyName\": \"DATAGROUP\",\n  \"companyUrl\": \"https://de.linkedin.com/company/datagroup-se\",\n  \"companyLogo\": \"https://media.licdn.com/dms/image/v2/C4D0BAQFCZT1emBoUsw/company-logo_200_200/company-logo_200_200/0/1630477221838/datagroup_ag_logo?e=2147483647&v=beta&t=kHRk6yObQhtWun4zVyZKfRI6iNwfH5xZ2aTfFnDTOjQ\",\n  \"country\": \"DE\",\n  \"city\": \"Krakau\",\n  \"latitude\": 51.36391,\n  \"longitude\": 11.857489,\n  \"industry\": \"IT-Dienstleistungen und IT-Beratung\",\n  \"skills\": \"\",\n  \"monthsOfExperience\": \"\",\n  \"educationLevel\": \"bachelor degree\",\n  \"url\": \"https://de.linkedin.com/jobs/view/python-developer-at-datagroup-4412111373\",\n  \"location\": \"Krakau, Saxony-Anhalt, Germany\"\n}\n```\n\nThe record above was produced with this input:\n\n```json\n{\n  \"searchQueries\": [\"Python Developer\"],\n  \"locations\": [\"Germany\"],\n  \"timeRange\": \"any\",\n  \"maxItems\": 10,\n  \"extractCompanyDetails\": false,\n  \"proxyConfiguration\": {\n    \"useApifyProxy\": true,\n    \"apifyProxyGroups\": [\"RESIDENTIAL\"]\n  }\n}\n```\n\n## Query and input reference\n\n| Input | Type | Required | Default | Accepted values | Description |\n|---|---|---|---|---|---|\n| `searchQueries` | array | No* | `[]` | Free-text keywords (prefill `Python Developer`) | Job titles or keywords. Each value is a separate search. Ignored when `startUrls` is provided |\n| `startUrls` | array (requestListSources) | No* | `[]` | LinkedIn job search URLs | URL-based entry point. Overrides `searchQueries` when provided |\n| `locations` | array | No | `[]` | Free-text locations (e.g. `Germany`, `London`) | Location filter applied to every search query |\n| `timeRange` | string | No | `any` | `any`, `past24Hours`, `pastWeek`, `pastMonth` | Filter jobs by posting date |\n| `jobType` | array | No | `[]` | `fullTime`, `partTime`, `contract`, `temporary`, `internship`, `volunteer` | Employment-type filter; empty means all types |\n| `experienceLevel` | array | No | `[]` | `internship`, `entryLevel`, `associate`, `midSenior`, `director`, `executive` | Experience-level filter; empty means all levels |\n| `remote` | array | No | `[]` | `onSite`, `remote`, `hybrid` | Work-arrangement filter; empty means all types |\n| `maxItems` | integer | No | `0` | `0` or any positive integer | Maximum jobs to collect; `0` = unlimited (Console prefill `10`) |\n| `extractCompanyDetails` | boolean | No | `false` | `true` / `false` | Attach company page fields onto each job record |\n| `maxConcurrency` | integer | No | `5` | `1`–`20` | Maximum parallel detail-page fetches |\n| `proxyConfiguration` | object | No | Apify proxy, `RESIDENTIAL` group | Apify proxy groups or custom proxies | Residential proxies are recommended |\n\n\\* Provide `searchQueries` or `startUrls` — at least one source is required to collect records.\n\nMinimal request:\n\n```json\n{ \"searchQueries\": [\"Python Developer\"], \"locations\": [\"Germany\"] }\n```\n\nAdvanced request (filters plus company page fields):\n\n```json\n{\n  \"searchQueries\": [\"Python Developer\"],\n  \"locations\": [\"Germany\"],\n  \"timeRange\": \"pastWeek\",\n  \"jobType\": [\"fullTime\"],\n  \"experienceLevel\": [\"midSenior\"],\n  \"remote\": [\"remote\", \"hybrid\"],\n  \"maxItems\": 500,\n  \"extractCompanyDetails\": true,\n  \"maxConcurrency\": 5,\n  \"proxyConfiguration\": { \"useApifyProxy\": true, \"apifyProxyGroups\": [\"RESIDENTIAL\"] }\n}\n```\n\n## Retrieve the data through the API\n\nThe Actor runs on the Apify platform, so there is no server to host and no crawling infrastructure to maintain.\n\n1. Start the Actor with a JSON input (console or API).\n2. Wait for the run to finish, or use a synchronous endpoint if you want the response inline.\n3. Retrieve items from the run's default dataset.\n4. Paginate or export the dataset.\n\nPython example:\n\n```python\nfrom apify_client import ApifyClient\n\nclient = ApifyClient(\"YOUR-APIFY-TOKEN\")\n\nrun_input = {\n    \"searchQueries\": [\"Python Developer\"],\n    \"locations\": [\"Germany\"],\n    \"maxItems\": 10,\n}\n\nrun = client.actor(\"datascrapers/linkedin-job-scraper\").call(run_input=run_input)\nfor item in client.dataset(run[\"defaultDatasetId\"]).iterate_items():\n    print(item[\"jobId\"], item[\"title\"], item[\"companyName\"])\n```\n\nApify generates ready-to-run Python, JavaScript, and cURL examples on the Actor's [API tab](https://apify.com/datascrapers/linkedin-job-scraper/api). Do not put a real API token in shared code or URLs.\n\n## Data quality and record handling\n\n- **Conditional fields**: company page fields are present only when `extractCompanyDetails` is enabled. Listings alone return the job fields in the data dictionary.\n- **Source changes**: LinkedIn page structure and values can change; fields the listing does not provide are returned as empty values rather than fabricated.\n- **Deduplication**: within a run, repeated `jobId` values are skipped. Across runs, the Actor does not deduplicate. Use `jobId` as the stable key, or `url` as a secondary key, and filter repeated runs against previously stored identifiers.\n- **Empty source values**: `skills` and `monthsOfExperience` are often empty strings when the listing does not publish them. `latitude` and `longitude` are omitted or empty when coordinates are not present.\n- **Normalization**: dates are stored as ISO 8601 strings; `country` is a country code; `employmentType` uses the listing value (for example `FULL_TIME`). Values are read from the listing and mapped to the field types in the data dictionary.\n\n## Export and pipeline examples\n\n| Destination | Recommended method | Typical use |\n|---|---|---|\n| PostgreSQL / Supabase | Dataset API poll or webhook consumer | Store job rows for labor-market or recruiting analysis |\n| Google Sheets | Apify Google Sheets integration | Share shortlists with recruiting or research teams |\n| ATS / CRM | Webhook on run completion | Push new jobs into sourcing pipelines |\n| S3 / cloud storage | Scheduled export via Apify scheduler + integration | Archival of hiring-market snapshots |\n\n## Pricing and cost examples\n\nThe Actor uses pay-per-event pricing. Live charges are:\n\n| Event | Trigger | Rate |\n|---|---|---|\n| Actor start | Once per run | $0.00005 |\n| Job result (`apify-default-dataset-item`) | Every job record written to the default dataset | $0.001 ($1 per 1,000 jobs) |\n\n`extractCompanyDetails` attaches company page fields onto the same job record. It is not a separate billed event.\n\nExample costs:\n\n| Records | Configuration | Estimated base cost |\n|---:|---|---:|\n| 1,000 | Jobs only | $1.00005 |\n| 10,000 | Jobs only | $10.00005 |\n| 1,000 | Jobs + company page fields | $1.00005 |\n| 10,000 | Jobs + company page fields | $10.00005 |\n\nCompute units and proxy traffic consumed by the run are billed by your Apify plan. Estimates depend on the verified pricing model and the options selected for the run.\n\n## Limitations and responsible data use\n\n- The Actor collects publicly accessible data from LinkedIn job pages only.\n- Field availability depends on what LinkedIn renders at run time; some values can be empty or missing, and site changes can alter fields.\n- Company page fields attach onto job records; they are not standalone dataset items.\n- The Actor does not provide historical snapshots unless you store them yourself.\n- Residential proxies are recommended; coverage may degrade without them.\n- You are responsible for compliance with LinkedIn's terms of service, applicable privacy law, and any contractual obligations before using the data.\n\n## Dataset questions\n\n### What does one dataset item represent?\n\nOne LinkedIn job. Company page fields attach onto that same row when `extractCompanyDetails` is enabled. Enabling company details does not create extra dataset items.\n\n### Which field should I use as a unique identifier?\n\n`jobId` is the LinkedIn job identifier and is the recommended deduplication key. `url` is a reasonable secondary key.\n\n### Are fields nullable or conditional?\n\nYes. Company page fields exist only when `extractCompanyDetails` is enabled. Within job records, fields the listing does not publish (commonly `skills` and `monthsOfExperience`) are returned as empty values.\n\n### Do startUrls override searchQueries?\n\nYes. When `startUrls` contains LinkedIn job search URLs, those URLs are used and `searchQueries` is ignored. Use `searchQueries` plus `locations` and filters when you want keyword search.\n\n### Can I retrieve the records as CSV or JSON?\n\nYes. The dataset can be exported as JSON, CSV, Excel, XML, or HTML from the Apify Console, and queried through the Dataset API.\n\n### Does the Actor return historical data?\n\nNo. Each run captures the state of the listings at run time. To track hiring changes over time, schedule repeated runs and store the outputs yourself.\n\n### What counts as a billable result?\n\nTwo charges apply: $0.00005 once per Actor start, and $0.001 for every job record written to the default dataset ($1 per 1,000 jobs). Company page fields do not add a billed event.\n\n## Related datasets from Data Scrapers\n\n- **[Dice.com Job Scraper](https://apify.com/datascrapers/dice-scraper)** — Technology job listings that can be compared with LinkedIn jobs by title, company, and skills.\n- **[Naukri Job Scraper](https://apify.com/datascrapers/naukri-scraper)** — India job listings that can be joined with LinkedIn rows by title and company for cross-board coverage.\n- **[Glassdoor Jobs Scraper](https://apify.com/datascrapers/glassdoor-jobs-scraper)** — Job listings with employer ratings that can be joined to LinkedIn jobs by company name and title.\n- **[ZipRecruiter Job Scraper](https://apify.com/datascrapers/ziprecruiter-scraper)** — US job listings for labor-market comparison against LinkedIn roles.\n- **[LinkedIn Company Scraper](https://apify.com/datascrapers/linkedin-company-scraper)** — Company profiles that can be joined with these job records by company name or `companyUrl`.\n- **[LinkedIn Profile Scraper](https://apify.com/datascrapers/linkedin-profile-scraper)** — Public profile records for hiring-team or candidate research alongside job listings.\n\n## Data Scrapers support\n\nNeed an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.\n",
    "actorDefinition": {
      "$schema": "https://apify.com/schemas/v1/actor.ide.json",
      "actorSpecification": 1,
      "name": "linkedin-job-scraper",
      "title": "LinkedIn Job Scraper",
      "description": "LinkedIn job dataset from keywords or search URLs, including title, company, location, employment type, and optional company-page fields.",
      "version": "0.1",
      "buildTag": "latest",
      "meta": {
        "templateId": "data-scrapers/linkedin-job-scraper",
        "generatedBy": "Data Scrapers"
      },
      "dockerfile": "../Dockerfile",
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "fields": {},
          "views": {
            "overview": {
              "title": "Overview",
              "transformation": {
                "fields": [
                  "jobId",
                  "title",
                  "companyName",
                  "companyUrl",
                  "location",
                  "city",
                  "country",
                  "datePosted",
                  "validThrough",
                  "employmentType",
                  "industry",
                  "monthsOfExperience",
                  "educationLevel",
                  "skills",
                  "description",
                  "companyLogo",
                  "url"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "jobId": {
                    "label": "Job ID",
                    "format": "text"
                  },
                  "title": {
                    "label": "Title",
                    "format": "text"
                  },
                  "companyName": {
                    "label": "Company",
                    "format": "text"
                  },
                  "companyUrl": {
                    "label": "Company URL",
                    "format": "link"
                  },
                  "location": {
                    "label": "Location",
                    "format": "text"
                  },
                  "city": {
                    "label": "City",
                    "format": "text"
                  },
                  "country": {
                    "label": "Country",
                    "format": "text"
                  },
                  "datePosted": {
                    "label": "Date posted",
                    "format": "date"
                  },
                  "validThrough": {
                    "label": "Valid through",
                    "format": "date"
                  },
                  "employmentType": {
                    "label": "Employment type",
                    "format": "text"
                  },
                  "industry": {
                    "label": "Industry",
                    "format": "text"
                  },
                  "monthsOfExperience": {
                    "label": "Experience (months)",
                    "format": "number"
                  },
                  "educationLevel": {
                    "label": "Education level",
                    "format": "text"
                  },
                  "skills": {
                    "label": "Skills",
                    "format": "text"
                  },
                  "description": {
                    "label": "Description",
                    "format": "text"
                  },
                  "companyLogo": {
                    "label": "Company logo",
                    "format": "image"
                  },
                  "url": {
                    "label": "URL",
                    "format": "link"
                  }
                }
              }
            }
          }
        },
        "keyValueStore": {
          "actorKeyValueStoreSchemaVersion": 1,
          "title": "LinkedIn Job Scraper Key-Value Store",
          "description": "Configuration, state, and output records stored by the Actor.",
          "collections": {
            "input": {
              "title": "Input",
              "description": "Actor input snapshot",
              "key": "INPUT",
              "contentTypes": [
                "application/json"
              ]
            },
            "state": {
              "title": "State",
              "description": "Actor persistence state",
              "keyPrefix": "STATE-",
              "contentTypes": [
                "application/json"
              ]
            }
          }
        }
      },
      "usesStandbyMode": true,
      "webServerSchema": {
        "openapi": "3.0.0",
        "info": {
          "title": "LinkedIn Job Scraper",
          "description": "Scrape LinkedIn job postings with advanced filters — location, time range, job type, experience level, and work type. Supports search queries or direct URLs. Optionally enriches results with full company details.",
          "version": "1.0.0"
        },
        "paths": {
          "/": {
            "get": {
              "summary": "Actor status",
              "description": "Returns the current status of the LinkedIn Job Scraper. Indicates whether the Actor is ready to accept scrape requests.",
              "responses": {
                "200": {
                  "description": "Actor is running and ready",
                  "content": {
                    "application/json": {
                      "schema": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string",
                            "example": "ready"
                          },
                          "actor": {
                            "type": "string",
                            "example": "linkedin-job-scraper"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "/scrape": {
            "post": {
              "summary": "Start a job scrape",
              "description": "Triggers a LinkedIn job search using the provided parameters and returns scraped job postings.",
              "requestBody": {
                "required": true,
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "properties": {
                        "searchQueries": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Job titles or keywords to search for",
                          "example": [
                            "Python Developer"
                          ]
                        },
                        "locations": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Location names to filter by",
                          "example": [
                            "Germany"
                          ]
                        },
                        "timeRange": {
                          "type": "string",
                          "enum": [
                            "any",
                            "past24Hours",
                            "pastWeek",
                            "pastMonth"
                          ],
                          "description": "Filter by posting date"
                        },
                        "jobType": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "fullTime",
                              "partTime",
                              "contract",
                              "temporary",
                              "internship",
                              "volunteer"
                            ]
                          },
                          "description": "Filter by employment type"
                        },
                        "experienceLevel": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "internship",
                              "entryLevel",
                              "associate",
                              "midSenior",
                              "director",
                              "executive"
                            ]
                          },
                          "description": "Filter by experience level"
                        },
                        "remote": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "onSite",
                              "remote",
                              "hybrid"
                            ]
                          },
                          "description": "Filter by work arrangement"
                        },
                        "maxItems": {
                          "type": "integer",
                          "minimum": 0,
                          "description": "Maximum jobs to scrape (0 = unlimited)",
                          "example": 10
                        },
                        "extractCompanyDetails": {
                          "type": "boolean",
                          "description": "Also fetch each company's full profile",
                          "example": false
                        }
                      }
                    }
                  }
                }
              },
              "responses": {
                "200": {
                  "description": "Scraping completed. Results are pushed to the default dataset.",
                  "content": {
                    "application/json": {
                      "schema": {
                        "type": "object",
                        "properties": {
                          "total": {
                            "type": "integer",
                            "example": 30
                          },
                          "datasetUrl": {
                            "type": "string",
                            "example": "https://api.apify.com/v2/datasets/abc123/items"
                          }
                        }
                      }
                    }
                  }
                },
                "400": {
                  "description": "Invalid input — no search queries or URLs provided"
                }
              }
            }
          }
        }
      },
      "input": {
        "title": "LinkedIn Job Scraper Input",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "searchQueries": {
            "title": "Search queries",
            "type": "array",
            "description": "Keywords or job titles to search for (e.g. 'Python Developer', 'Data Scientist'). Each query produces a separate search.",
            "editor": "stringList",
            "default": [],
            "prefill": [
              "Python Developer"
            ]
          },
          "startUrls": {
            "title": "Start URLs",
            "type": "array",
            "description": "Direct LinkedIn job search URLs. Overrides searchQueries when provided.",
            "editor": "requestListSources",
            "default": [],
            "prefill": []
          },
          "locations": {
            "title": "Locations",
            "type": "array",
            "description": "Location names to filter jobs (e.g. 'Germany', 'United States', 'London'). Applied to all search queries.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "timeRange": {
            "title": "Time range",
            "type": "string",
            "description": "Filter jobs by posting date.",
            "enum": [
              "any",
              "past24Hours",
              "pastWeek",
              "pastMonth"
            ],
            "enumTitles": [
              "Any time",
              "Past 24 hours",
              "Past week",
              "Past month"
            ],
            "default": "any"
          },
          "jobType": {
            "title": "Job type",
            "type": "array",
            "description": "Filter by employment type. Leave empty for all types.",
            "editor": "select",
            "default": [],
            "items": {
              "type": "string",
              "enum": [
                "fullTime",
                "partTime",
                "contract",
                "temporary",
                "internship",
                "volunteer"
              ],
              "enumTitles": [
                "Full-time",
                "Part-time",
                "Contract",
                "Temporary",
                "Internship",
                "Volunteer"
              ]
            }
          },
          "experienceLevel": {
            "title": "Experience level",
            "type": "array",
            "description": "Filter by required experience level. Leave empty for all levels.",
            "editor": "select",
            "default": [],
            "items": {
              "type": "string",
              "enum": [
                "internship",
                "entryLevel",
                "associate",
                "midSenior",
                "director",
                "executive"
              ],
              "enumTitles": [
                "Internship",
                "Entry level",
                "Associate",
                "Mid-senior level",
                "Director",
                "Executive"
              ]
            }
          },
          "remote": {
            "title": "Remote / Work type",
            "type": "array",
            "description": "Filter by work arrangement. Leave empty for all types.",
            "editor": "select",
            "default": [],
            "items": {
              "type": "string",
              "enum": [
                "onSite",
                "remote",
                "hybrid"
              ],
              "enumTitles": [
                "On-site",
                "Remote",
                "Hybrid"
              ]
            }
          },
          "maxItems": {
            "title": "Max items",
            "type": "integer",
            "description": "Maximum number of job postings to scrape. 0 = unlimited.",
            "default": 0,
            "minimum": 0,
            "prefill": 10
          },
          "extractCompanyDetails": {
            "title": "Extract company details",
            "type": "boolean",
            "description": "When enabled, also scrapes each company's LinkedIn page for full company details (description, followers, specialties, etc.) and appends them to the output.",
            "default": false,
            "prefill": false
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "type": "integer",
            "description": "Maximum number of parallel detail page fetches. Higher values increase speed but may trigger rate limiting. Recommended: 3-10.",
            "default": 5,
            "minimum": 1,
            "maximum": 20,
            "prefill": 5
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Proxy settings for anti-bot protection.",
            "editor": "proxy",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          }
        },
        "required": []
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "LinkedIn Job Scraper Output",
        "properties": {
          "dataset": {
            "type": "string",
            "title": "Job postings dataset",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "readme": "**LinkedIn Job Scraper** creates a structured dataset of job postings collected from [LinkedIn](https://www.linkedin.com). Each dataset item represents one LinkedIn job and can include identifiers, title, description, posting dates, employment type, company name and URL, location fields, coordinates, industry, skills, experience, and education. Query the source with keyword searches (`searchQueries`) plus locations and filters, or with LinkedIn job search URLs in `startUrls` (these override `searchQueries` when provided). Control the result limit with `maxItems`, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, XML, or another supported format.\n\n## Dataset at a glance\n\n| Property | Value |\n|---|---|\n| Source | linkedin.com (public job listings) |\n| Record unit | One LinkedIn job |\n| Input methods | Keyword search (`searchQueries`) plus `locations` and filters, or LinkedIn job search URLs (`startUrls`) |\n| Main identifiers | `jobId`, `url` |\n| Delivery | Apify Dataset and API |\n| Export formats | JSON, CSV, Excel, XML, HTML (Apify dataset exports) |\n| Update model | Fresh records per Actor run |\n| Pricing | $0.00005 per Actor start; $0.001 per job ($1 per 1,000 jobs) |\n\n## Coverage and available records\n\nThe Actor collects public LinkedIn job listings using one of two entry points:\n\n- **Search-based**: Set `searchQueries` to job titles or keywords (for example `Python Developer`). Each query is a separate search. `locations` applies to every query. Filters (`timeRange`, `jobType`, `experienceLevel`, `remote`) narrow the search.\n- **URL-based**: Pass LinkedIn job search URLs in `startUrls`. When `startUrls` is provided, `searchQueries` is ignored.\n\nRecord types and limits:\n\n- **Job records** are always collected: `jobId`, title, description, dates, employment type, company name and URL, location fields, coordinates, industry, skills, experience, education, and the job URL.\n- **Company page fields** are conditional: they attach onto the same job record only when `extractCompanyDetails` is enabled. They are not a separate dataset item.\n- **Result cap**: `maxItems` limits the number of jobs collected (`0` means unlimited, the default; Console prefill is `10`).\n\nKnown exclusions: content LinkedIn only shows behind login is not collected; each run captures listing state at run time (no historical snapshots); company page fields are omitted when `extractCompanyDetails` is off or the company page is unavailable.\n\n## Data dictionary\n\nField names below match dataset record JSON properties exactly. `jobId` is the recommended deduplication key; `url` is a reasonable secondary key. Dates are ISO 8601 timestamps as returned on the listing (for example `2026-05-08T13:38:46.000Z`). `country` is a country code. `latitude` and `longitude` are decimal degrees when present.\n\n| Field | Type | Nullable | Description | Example |\n|---|---|---:|---|---|\n| `jobId` | string | No | LinkedIn job identifier; best stable deduplication key | `4412111373` |\n| `title` | string | No | Job title | `Python Developer` |\n| `description` | string | Yes | Full job description text | See example record |\n| `datePosted` | string | Yes | Posting timestamp (ISO 8601) | `2026-05-08T13:38:46.000Z` |\n| `validThrough` | string | Yes | Listing end timestamp (ISO 8601) | `2026-11-04T13:38:46.000Z` |\n| `employmentType` | string | Yes | Employment type as shown on the listing | `FULL_TIME` |\n| `companyName` | string | Yes | Hiring company name | `DATAGROUP` |\n| `companyUrl` | string | Yes | LinkedIn company page URL | `https://de.linkedin.com/company/datagroup-se` |\n| `companyLogo` | string | Yes | Company logo image URL | See example record |\n| `country` | string | Yes | Country code | `DE` |\n| `city` | string | Yes | City as shown on the listing | `Krakau` |\n| `latitude` | number | Yes | Location latitude in decimal degrees | `51.36391` |\n| `longitude` | number | Yes | Location longitude in decimal degrees | `11.857489` |\n| `industry` | string | Yes | Industry text as shown on the listing | `IT-Dienstleistungen und IT-Beratung` |\n| `skills` | string | Yes | Skills text; empty when the listing does not provide it | `\"\"` |\n| `monthsOfExperience` | string | Yes | Experience requirement as returned on the listing; empty when not provided | `\"\"` |\n| `educationLevel` | string | Yes | Education requirement as shown on the listing | `bachelor degree` |\n| `url` | string | No | Job posting URL; secondary deduplication key | `https://de.linkedin.com/jobs/view/python-developer-at-datagroup-4412111373` |\n| `location` | string | Yes | Full location string (city, region, country) | `Krakau, Saxony-Anhalt, Germany` |\n\nWhen `extractCompanyDetails` is true, company page fields attach onto this same job record. They are omitted when the toggle is off.\n\n## Example dataset record\n\nReal record produced with the test input below (`searchQueries`: `Python Developer`, `locations`: `Germany`, `maxItems`: `10`). The `description` text is shortened for readability; the live record contains the full listing copy.\n\n```json\n{\n  \"jobId\": \"4412111373\",\n  \"title\": \"Python Developer\",\n  \"description\": \"Job Description DATAGROUP Polska. Design and implement robust, scalable, and efficient JAVA-based frontend as well as Python components for the ETL process.\",\n  \"datePosted\": \"2026-05-08T13:38:46.000Z\",\n  \"validThrough\": \"2026-11-04T13:38:46.000Z\",\n  \"employmentType\": \"FULL_TIME\",\n  \"companyName\": \"DATAGROUP\",\n  \"companyUrl\": \"https://de.linkedin.com/company/datagroup-se\",\n  \"companyLogo\": \"https://media.licdn.com/dms/image/v2/C4D0BAQFCZT1emBoUsw/company-logo_200_200/company-logo_200_200/0/1630477221838/datagroup_ag_logo?e=2147483647&v=beta&t=kHRk6yObQhtWun4zVyZKfRI6iNwfH5xZ2aTfFnDTOjQ\",\n  \"country\": \"DE\",\n  \"city\": \"Krakau\",\n  \"latitude\": 51.36391,\n  \"longitude\": 11.857489,\n  \"industry\": \"IT-Dienstleistungen und IT-Beratung\",\n  \"skills\": \"\",\n  \"monthsOfExperience\": \"\",\n  \"educationLevel\": \"bachelor degree\",\n  \"url\": \"https://de.linkedin.com/jobs/view/python-developer-at-datagroup-4412111373\",\n  \"location\": \"Krakau, Saxony-Anhalt, Germany\"\n}\n```\n\nThe record above was produced with this input:\n\n```json\n{\n  \"searchQueries\": [\"Python Developer\"],\n  \"locations\": [\"Germany\"],\n  \"timeRange\": \"any\",\n  \"maxItems\": 10,\n  \"extractCompanyDetails\": false,\n  \"proxyConfiguration\": {\n    \"useApifyProxy\": true,\n    \"apifyProxyGroups\": [\"RESIDENTIAL\"]\n  }\n}\n```\n\n## Query and input reference\n\n| Input | Type | Required | Default | Accepted values | Description |\n|---|---|---|---|---|---|\n| `searchQueries` | array | No* | `[]` | Free-text keywords (prefill `Python Developer`) | Job titles or keywords. Each value is a separate search. Ignored when `startUrls` is provided |\n| `startUrls` | array (requestListSources) | No* | `[]` | LinkedIn job search URLs | URL-based entry point. Overrides `searchQueries` when provided |\n| `locations` | array | No | `[]` | Free-text locations (e.g. `Germany`, `London`) | Location filter applied to every search query |\n| `timeRange` | string | No | `any` | `any`, `past24Hours`, `pastWeek`, `pastMonth` | Filter jobs by posting date |\n| `jobType` | array | No | `[]` | `fullTime`, `partTime`, `contract`, `temporary`, `internship`, `volunteer` | Employment-type filter; empty means all types |\n| `experienceLevel` | array | No | `[]` | `internship`, `entryLevel`, `associate`, `midSenior`, `director`, `executive` | Experience-level filter; empty means all levels |\n| `remote` | array | No | `[]` | `onSite`, `remote`, `hybrid` | Work-arrangement filter; empty means all types |\n| `maxItems` | integer | No | `0` | `0` or any positive integer | Maximum jobs to collect; `0` = unlimited (Console prefill `10`) |\n| `extractCompanyDetails` | boolean | No | `false` | `true` / `false` | Attach company page fields onto each job record |\n| `maxConcurrency` | integer | No | `5` | `1`–`20` | Maximum parallel detail-page fetches |\n| `proxyConfiguration` | object | No | Apify proxy, `RESIDENTIAL` group | Apify proxy groups or custom proxies | Residential proxies are recommended |\n\n\\* Provide `searchQueries` or `startUrls` — at least one source is required to collect records.\n\nMinimal request:\n\n```json\n{ \"searchQueries\": [\"Python Developer\"], \"locations\": [\"Germany\"] }\n```\n\nAdvanced request (filters plus company page fields):\n\n```json\n{\n  \"searchQueries\": [\"Python Developer\"],\n  \"locations\": [\"Germany\"],\n  \"timeRange\": \"pastWeek\",\n  \"jobType\": [\"fullTime\"],\n  \"experienceLevel\": [\"midSenior\"],\n  \"remote\": [\"remote\", \"hybrid\"],\n  \"maxItems\": 500,\n  \"extractCompanyDetails\": true,\n  \"maxConcurrency\": 5,\n  \"proxyConfiguration\": { \"useApifyProxy\": true, \"apifyProxyGroups\": [\"RESIDENTIAL\"] }\n}\n```\n\n## Retrieve the data through the API\n\nThe Actor runs on the Apify platform, so there is no server to host and no crawling infrastructure to maintain.\n\n1. Start the Actor with a JSON input (console or API).\n2. Wait for the run to finish, or use a synchronous endpoint if you want the response inline.\n3. Retrieve items from the run's default dataset.\n4. Paginate or export the dataset.\n\nPython example:\n\n```python\nfrom apify_client import ApifyClient\n\nclient = ApifyClient(\"YOUR-APIFY-TOKEN\")\n\nrun_input = {\n    \"searchQueries\": [\"Python Developer\"],\n    \"locations\": [\"Germany\"],\n    \"maxItems\": 10,\n}\n\nrun = client.actor(\"datascrapers/linkedin-job-scraper\").call(run_input=run_input)\nfor item in client.dataset(run[\"defaultDatasetId\"]).iterate_items():\n    print(item[\"jobId\"], item[\"title\"], item[\"companyName\"])\n```\n\nApify generates ready-to-run Python, JavaScript, and cURL examples on the Actor's [API tab](https://apify.com/datascrapers/linkedin-job-scraper/api). Do not put a real API token in shared code or URLs.\n\n## Data quality and record handling\n\n- **Conditional fields**: company page fields are present only when `extractCompanyDetails` is enabled. Listings alone return the job fields in the data dictionary.\n- **Source changes**: LinkedIn page structure and values can change; fields the listing does not provide are returned as empty values rather than fabricated.\n- **Deduplication**: within a run, repeated `jobId` values are skipped. Across runs, the Actor does not deduplicate. Use `jobId` as the stable key, or `url` as a secondary key, and filter repeated runs against previously stored identifiers.\n- **Empty source values**: `skills` and `monthsOfExperience` are often empty strings when the listing does not publish them. `latitude` and `longitude` are omitted or empty when coordinates are not present.\n- **Normalization**: dates are stored as ISO 8601 strings; `country` is a country code; `employmentType` uses the listing value (for example `FULL_TIME`). Values are read from the listing and mapped to the field types in the data dictionary.\n\n## Export and pipeline examples\n\n| Destination | Recommended method | Typical use |\n|---|---|---|\n| PostgreSQL / Supabase | Dataset API poll or webhook consumer | Store job rows for labor-market or recruiting analysis |\n| Google Sheets | Apify Google Sheets integration | Share shortlists with recruiting or research teams |\n| ATS / CRM | Webhook on run completion | Push new jobs into sourcing pipelines |\n| S3 / cloud storage | Scheduled export via Apify scheduler + integration | Archival of hiring-market snapshots |\n\n## Pricing and cost examples\n\nThe Actor uses pay-per-event pricing. Live charges are:\n\n| Event | Trigger | Rate |\n|---|---|---|\n| Actor start | Once per run | $0.00005 |\n| Job result (`apify-default-dataset-item`) | Every job record written to the default dataset | $0.001 ($1 per 1,000 jobs) |\n\n`extractCompanyDetails` attaches company page fields onto the same job record. It is not a separate billed event.\n\nExample costs:\n\n| Records | Configuration | Estimated base cost |\n|---:|---|---:|\n| 1,000 | Jobs only | $1.00005 |\n| 10,000 | Jobs only | $10.00005 |\n| 1,000 | Jobs + company page fields | $1.00005 |\n| 10,000 | Jobs + company page fields | $10.00005 |\n\nCompute units and proxy traffic consumed by the run are billed by your Apify plan. Estimates depend on the verified pricing model and the options selected for the run.\n\n## Limitations and responsible data use\n\n- The Actor collects publicly accessible data from LinkedIn job pages only.\n- Field availability depends on what LinkedIn renders at run time; some values can be empty or missing, and site changes can alter fields.\n- Company page fields attach onto job records; they are not standalone dataset items.\n- The Actor does not provide historical snapshots unless you store them yourself.\n- Residential proxies are recommended; coverage may degrade without them.\n- You are responsible for compliance with LinkedIn's terms of service, applicable privacy law, and any contractual obligations before using the data.\n\n## Dataset questions\n\n### What does one dataset item represent?\n\nOne LinkedIn job. Company page fields attach onto that same row when `extractCompanyDetails` is enabled. Enabling company details does not create extra dataset items.\n\n### Which field should I use as a unique identifier?\n\n`jobId` is the LinkedIn job identifier and is the recommended deduplication key. `url` is a reasonable secondary key.\n\n### Are fields nullable or conditional?\n\nYes. Company page fields exist only when `extractCompanyDetails` is enabled. Within job records, fields the listing does not publish (commonly `skills` and `monthsOfExperience`) are returned as empty values.\n\n### Do startUrls override searchQueries?\n\nYes. When `startUrls` contains LinkedIn job search URLs, those URLs are used and `searchQueries` is ignored. Use `searchQueries` plus `locations` and filters when you want keyword search.\n\n### Can I retrieve the records as CSV or JSON?\n\nYes. The dataset can be exported as JSON, CSV, Excel, XML, or HTML from the Apify Console, and queried through the Dataset API.\n\n### Does the Actor return historical data?\n\nNo. Each run captures the state of the listings at run time. To track hiring changes over time, schedule repeated runs and store the outputs yourself.\n\n### What counts as a billable result?\n\nTwo charges apply: $0.00005 once per Actor start, and $0.001 for every job record written to the default dataset ($1 per 1,000 jobs). Company page fields do not add a billed event.\n\n## Related datasets from Data Scrapers\n\n- **[Dice.com Job Scraper](https://apify.com/datascrapers/dice-scraper)** — Technology job listings that can be compared with LinkedIn jobs by title, company, and skills.\n- **[Naukri Job Scraper](https://apify.com/datascrapers/naukri-scraper)** — India job listings that can be joined with LinkedIn rows by title and company for cross-board coverage.\n- **[Glassdoor Jobs Scraper](https://apify.com/datascrapers/glassdoor-jobs-scraper)** — Job listings with employer ratings that can be joined to LinkedIn jobs by company name and title.\n- **[ZipRecruiter Job Scraper](https://apify.com/datascrapers/ziprecruiter-scraper)** — US job listings for labor-market comparison against LinkedIn roles.\n- **[LinkedIn Company Scraper](https://apify.com/datascrapers/linkedin-company-scraper)** — Company profiles that can be joined with these job records by company name or `companyUrl`.\n- **[LinkedIn Profile Scraper](https://apify.com/datascrapers/linkedin-profile-scraper)** — Public profile records for hiring-team or candidate research alongside job listings.\n\n## Data Scrapers support\n\nNeed an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.\n"
    },
    "buildNumber": "0.1.3",
    "imageDigest": "bbfc3888b948b5635f7217287fafd2d3190b1670cfdfddbf38ab51ccb8bda30b",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "0.1"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.002871111111111111
    }
  }
}