LinkedIn Job Market Report — Demand, Top Hiring Companies
Pricing
from $24.00 / 1,000 market reports
LinkedIn Job Market Report — Demand, Top Hiring Companies
A LinkedIn job market report per keyword and location: roles read, how many LinkedIn shows, top hiring companies, job titles and places, remote share and fresh postings. Run it again for the change since the last run: new companies and rank moves. $0.03 per report. No login.
Pricing
from $24.00 / 1,000 market reports
Rating
0.0
(0)
Developer
Northbell
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Give it a list of markets — a keyword in a place, like react developer | Berlin, Germany — and get one report row per market: how many roles it read, how many LinkedIn says exist, who is hiring (top 15 companies), the title mix, the places, the remote share and how many postings are fresh. $0.03 per report ($30 per 1,000), no login, no cookies.
Run it again — or put it on a weekly schedule — and every report also tells you what changed since the last run: which companies are new in the market, how the top companies moved up or down (previousRank, rankChange, positive = moved up), and how many more or fewer roles it read. LinkedIn only shows you today's market; this keeps the history.
What you get
One row per market (type: "market"):
| Field | What it is |
|---|---|
keywords, location, datePosted, searchUrl | the market and the LinkedIn search page it comes from |
jobsRead, maxJobsPerMarket, stoppedBy, note | how many distinct postings were read. stoppedBy is cap (your limit), end (LinkedIn's public list had no more to give — this can be far fewer than the total it prints, see Notes) error (then note says what happened) or time (the run was about to reach its time limit; note says so) |
totalShownByLinkedIn, totalShownText, totalShownIsLowerBound, totalShownPlace, totalShownNote | the number LinkedIn prints above the results. Big markets show as a rounded floor such as 1,000+ or 10,000+ (totalShownIsLowerBound: true). totalShownNote appears only when the number is missing or answers for another place, and says why |
shareOfTotalRead | jobsRead as a share of the exact total LinkedIn prints (0.147 = you read 15% of it); null when the total is missing or a floor like 10,000+ |
postedLast24h, postedLast7d | postings by posting date: dated today or yesterday (UTC), and dated within the last 7 days |
remoteShare, activelyHiringShare | share of postings whose title or place says "Remote", and share with LinkedIn's "Actively Hiring" badge |
distinctCompanies, top5CompaniesShare | how many companies are hiring, and how much of the market the five biggest hold |
topCompanies | top 15: company, slug (LinkedIn's company page name, null when the posting links none), jobs, rank, previousRank, rankChange, jobsChange, isNew |
topTitles | top 15 job titles with jobs — normalised, so "Data Engineer (m/w/d)", "Data Engineer - Remote" and "Sr. Data Engineer" fall into the right groups |
topLocations | top 10 places with jobs |
previousObservedAt, jobsReadChange, totalShownChange, postedLast7dChange | the change since your previous run of the same market (null on the first run) |
newCompaniesCount, newCompaniesSinceLastRun | companies hiring now that were not in the previous run (top 15 listed, with jobs; an empty list when nothing is new) |
requestsUsed | HTTP requests this report took, retries included |
observedAt | when it was read |
With Include job details on, the row also has: detailsRead (of detailsAsked), seniorityMix, employmentTypeMix (each [{level or type, jobs, share}]), easyApplyShare, and detailsNote when too few job pages could be read.
Error rows (type: "error": keywords, location, message) are free.
Use it for
- Hiring and recruiting — see which companies are competing for the same people in your city, and which just started
- Career moves and salary talks — how deep is the market for your title in a place, and how much of it is remote
- Sales and lead generation — companies hiring in a field are companies with budget for it;
newCompaniesSinceLastRunis a weekly lead list - Market research and newsletters — demand by role and place, tracked the same way every week
Input
{"markets": [{ "keywords": "data engineer", "location": "United States" },"react developer | Berlin, Germany"],"maxJobsPerMarket": 200,"datePosted": "past-week"}
markets— up to 100 per run. Objects withkeywordsandlocation, or the short string"keywords | location". Put them all in one run and you pay the start fee once.maxJobsPerMarket— default 200, up to 1,000. Ten postings per request.datePosted—past-week(default),past-24-hours,past-monthorany.includeDetails— defaultfalse. Opens a sample of job pages for the seniority mix, employment-type mix and Easy Apply share (see Pricing).detailsPerMarket— job pages to open per market when details are on: 30 by default, 10 to 100, spread evenly over the postings read.
The history is kept per market, period and size in a named key-value store in your Apify account, so the second run already shows changes. Schedule it (Apify → Schedules) for a weekly log. Changing datePosted or maxJobsPerMarket starts a new history for that market.
Pricing
$0.03 per market report, plus $0.01 per run. A report that reads 200 postings takes about 21 requests (20 pages of results and 1 for the total); at 1,000 postings about 101; a search whose public list is shorter takes fewer. LinkedIn is read at 30 requests a minute, so a 200-posting report takes about 40 seconds: a run of 100 markets at that size needs more than the default 1-hour run timeout, so lower maxJobsPerMarket or raise the timeout. Each report is saved as soon as it is done. Error rows (markets that could not be read) are free. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing.
With Include job details on, a report costs $0.10 instead ($100 per 1,000) and takes up to detailsPerMarket more requests (30 by default). If too few job pages could be read to give a mix, the report is kept and charged as a plain one.
Notes
- Public data only: what anyone sees on LinkedIn without signing in. No login, no cookies; the Actor cannot send either. No people are read — only job postings, company names and places.
- The lists come from the postings read, which can be a small part of the market. The company, title and place lists are ranked by the number of postings among the postings read. LinkedIn serves anonymous visitors at most the first 1,000 postings of a search, and for many searches the public list ends much earlier: in October 2026 a search that printed "4,000+" listed 100 postings and one that printed 680 listed 100 (
stoppedBy: "end"). SostoppedBy: "end"means LinkedIn had nothing more to show, not that you have the whole market. ComparejobsReadwithtotalShownByLinkedIn(shareOfTotalRead) to see how much of it a report covers, and compare markets with each other by shares (remoteShare,top5CompaniesShare) rather than by raw counts. - "New since last run" compares what each run could read. A company shows as new when it was not in the previous run's list; with a list that is a ranked slice of a bigger market (
stoppedByiscap, orendwell short of the total) it can also mean it moved into the slice. Narrow the market (one city,past-24-hours) for steadier changes. A run cut short by an error (stoppedBy: "error") is not saved, so the next run is compared with the last complete one. totalShownByLinkedIncan be empty. It comes from LinkedIn's public search page, which sometimes answers for a different place than the one you asked for (we saw "Berlin, Germany" answered as the district "Köpenick"). Then the number is not used, it isnull, andtotalShownNotesays what happened; the same field is also empty when that page could not be read. It never fails the report.totalShownChangeis only filled when both totals are exact (not10,000+). A place LinkedIn does not recognise is widened to a bigger one (a made-up town came back as the whole United States): checktopLocationsagainst the place you asked for.- Dates have no time of day. LinkedIn publishes the posting date, so
postedLast24hcounts postings dated today or yesterday (UTC), andpostedLast7dthose dated within 7 days. Choosingpast-weekmakespostedLast7dabout equal tojobsRead; chooseanyorpast-monthto see the age mix. remoteShareis a floor. The public job list has no workplace-type field, so it counts postings that say "Remote" in the title or place ("Remote Sensing" excepted).- Job details are a sample.
seniorityMix,employmentTypeMixandeasyApplyShareare computed over the job pages read (detailsRead), not the whole market.easyApplyShareis the share of postings where you apply on LinkedIn itself (LinkedIn's public page shows an Apply button without the external-link arrow); the rest send you to the company's own site. Postings that state no seniority or employment type are left out of that mix.seniorityMixuses LinkedIn's own levels, including "Not Applicable". - Not included: salary (see the salary Actor below), job descriptions, applicant counts. Fields from job pages are empty unless Include job details is on.
- If LinkedIn stops answering part-way, a report built from at least 30 postings is kept and marked
stoppedBy: "error"with anote; with fewer you get a free error row. After three markets in a row that LinkedIn refuses, the rest of the run is skipped instead of waiting for each. Two minutes before the run's time limit the market in progress stops the same way (stoppedBy: "time"), and the markets not started come back as freekind: "time-limit"rows, so nothing read is lost to a timeout. rankis shared between companies with the same number of postings (1, 1, 1, 4), so a new company does not push the tied ones down.
Need the postings themselves, pay or one company's openings?
- Fast LinkedIn Jobs Scraper — the job rows behind a market, cheap and quick
- LinkedIn Salary Benchmark — pay ranges for the same roles
- LinkedIn Company Jobs Scraper — every open role at a company from
topCompanies
For AI agents
{"markets": ["data engineer | United States"], "maxJobsPerMarket": 100} returns one row with jobsRead, totalShownByLinkedIn, topCompanies, topTitles, remoteShare and the change since the last run. Rows have type: market or error. Pass several markets in one run to compare them. jobsRead is the size of the sample behind the lists (LinkedIn's public list often ends at 100); for demand use totalShownByLinkedIn when it is present and not a floor (totalShownIsLowerBound: false), and compare the lists by shares (remoteShare, top5CompaniesShare).