LinkedIn Jobs Scraper & LinkedIn Jobs API: Job Postings Data avatar

LinkedIn Jobs Scraper & LinkedIn Jobs API: Job Postings Data

Pricing

from $1.00 / 1,000 jobs

Go to Apify Store
LinkedIn Jobs Scraper & LinkedIn Jobs API: Job Postings Data

LinkedIn Jobs Scraper & LinkedIn Jobs API: Job Postings Data

LinkedIn jobs API and scraper, no login: search LinkedIn job listings by keywords and location with LinkedIn's filters (date, company, Easy Apply, under 10 applicants); each job posting with description, salary, seniority, applicants and company facts; a job by URL or id.

Pricing

from $1.00 / 1,000 jobs

Rating

0.0

(0)

Developer

Hyperbach

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

3 days ago

Last modified

Share

LinkedIn job listings as data, logged out: keywords and a location in (or LinkedIn search URLs, several searches with their own filters), one row per job out — id and URL, title, company with its LinkedIn URL and logo, location, the posted date from the card itself, the applicants text with its floor and ceiling ("Be among the first 25" = 0–24, never 25), the salary from LinkedIn's own salary block only, seniority, employment type, industries, Easy Apply or external apply, the closed flag, the full description as HTML and text — and the company's public facts once per company (website, size, headquarters, industry, founded, specialties, followers, description). A free summary row per search carries LinkedIn's own count ("11,000+" or an exact "22"), what was read and a completeness verdict: COMPLETE, TRUNCATED (LinkedIn's list ends at 1,000 a search), CAPPED (your limit) or PARTIAL. LinkedIn's own filters go into the request (date posted, any date window, company, Easy Apply, under 10 applicants, geoId and distance); experience level, job type and workplace are checked on each job's page because LinkedIn's logged-out search ignores them, and a miss is dropped free. Past the 1,000 cap, deepSearch reads nested date windows, every job once. A job by URL or id in, its posting out; includeExpiry adds the expiry date and the exact posting time. An id LinkedIn does not know, a value that is no job or search, a repeated input: free typed rows. Your own id travels with every row. No login, no LinkedIn account, no cookie, no API key, proxies handled for you.

Why this LinkedIn jobs scraper

  • Every value as LinkedIn states it, never a guess. The applicants text is kept and typed with its floor and ceiling ("Be among the first 25 applicants" = applicants_min 0, applicants_max 24; "Over 200" = 201 and open; "57 applicants" = 57), where the lane's leader writes 25 for "first 25" on 67 of 100 rows. The salary comes from LinkedIn's own salary block only, never parsed out of a description written for another city. The posted date is the card's own <time datetime>, never computed from "2 weeks ago". The apply type is the page's button (Easy Apply or the employer's site); the employer's apply URL and the job function are not on any logged-out page, so they are not columns here (nobody logged out has them: 0 of 501 pages on our study).
  • Depth with a proof. The public search page gives LinkedIn's own count ("11,000+", or an exact "22 Python Jobs in Boise") and the guest list is walked to its end: an empty page read twice, or LinkedIn's own cap of 1,000 a search. The free search row states the count, the distinct jobs read and delivered, the calls, and the verdict COMPLETE / TRUNCATED / CAPPED / PARTIAL with its reason, so a short dataset is never silent (the lane's most frequent complaint: 110 issues on depth). deepSearch goes past the cap by nested date windows (30 days, 7 days, 24 hours, 6 hours, 1 hour), each its own slice of up to 1,000 more, every job once; the row names each window's count and what it added.
  • Filters that hold, free when they miss. Date posted (LinkedIn's presets or any window in seconds), company, Easy Apply, under 10 applicants, geoId and distance go into LinkedIn's own request. LinkedIn's logged-out search ignores its experience, job-type and workplace filters (measured: 10 of 10 pages identical to the control), so those are checked on each job's own page — Seniority level, Employment type, the posting's own workplace words — and a job that does not match is dropped before it is charged; the summary row counts the drops. Title and company word filters apply on the card before any page is read.
  • The whole posting, and the company's facts. Every job row carries the description whole (HTML and text), seniority, employment type, industries as LinkedIn lists them, the apply type, the closed flag (a closed job is delivered flagged, never dropped silently), the card's badge ("Actively Hiring"), and — once per company, cached a week on our side — the company's public page: website, industry, size with its bounds, headquarters, type, founded, specialties, followers, employees on LinkedIn, tagline, description.
  • Honest billing. One job asked = one job charged, no minimum; the summary row, an unknown id, a repeated input, a filtered or dropped card, a failed page, a job an earlier run of the same memory delivered: free. A job is charged once a run whatever searches overlap. A run that stops early (a timeout, an abort) is charged for the rows it delivered, and every search in progress gets a PARTIAL row with what it read.
  • Plain HTTP, paced by the measurement. LinkedIn's guest job surfaces answer a plain request with a current browser fingerprint, no cookie, no token, no warm-up; the limit is a per-call soft challenge (about 1 in 5 calls, answered on the same session after one second) and a short-window wall at 2 calls a second, so every session paces at 1 call a second and a session challenged four times in a row is replaced. On our tests 4 sessions read about 180 jobs a minute with the posting; a 40-job search with company facts took 60 seconds, a 1,000-job search about 6 minutes.

Who it's for

  • Recruiters, sourcers and job-market analysts — every job of a search with the whole posting, the applicants floor and the salary block, past the first screen; a city, a company or a date window as the slice; a scheduled task with onlyNewJobs or a one-hour window for the new postings.
  • Lead-generation and sales tools — the companies hiring for a role in a region, with each company's size, industry, headquarters, website and followers on every row; Easy Apply or external apply tells a direct employer from an agency's board.
  • Job boards and aggregators — the posting as HTML and text with id, URL, company URL and logo, the card's date and the expiry date on request, de-duplicated across searches, with a verdict row per search to reconcile against.
  • Developers and data teams — typed rows keyed by search_id and your own input_id, a free summary row per search with the count and verdict, a job by URL or id, a run summary to check a pipeline against, every input constrained in the schema.

Quick start

The 100 newest Python jobs in the United States, with the posting and the company

{
"keywords": "python",
"location": "United States",
"maxItemsPerSearch": 100
}

Every Entry-level remote data job posted this week, several searches with your ids

{
"searches": [
{
"keywords": "data engineer",
"location": "United States",
"id": "de-us"
},
{
"keywords": "data analyst",
"location": "Canada",
"id": "da-ca"
}
],
"datePosted": "week",
"experienceLevels": [
"Entry level"
],
"workplaceTypes": [
"Remote"
],
"maxItemsPerSearch": 200
}

A LinkedIn search URL as it is, past LinkedIn's 1,000 cap

{
"searches": [
"https://www.linkedin.com/jobs/search?keywords=python&location=Germany&f_TPR=r604800"
],
"deepSearch": true
}

Jobs by URL or id, with the expiry date and the exact posting time

{
"jobUrls": [
"https://www.linkedin.com/jobs/view/senior-software-engineer-python-at-venmo-4465379983",
"4432486930"
],
"includeExpiry": true
}

Output

One row per job (and one free summary row per search):

fieldmeaning
row_typejob (one job: charged as a job with its posting, as a card row without) or search (the free summary of a search with LinkedIn's count and the verdict).
search_ids1, s2, … in the order of the inputs: the search or job input this row answers.
search_labelThe input as you gave it (the keywords, the URL or the job id).
input_idYour own id from a search object, carried on every row it produces.
statusA job row: ok (charged), not_found, failed, invalid, duplicate, not_read (free). A search row: ok, no_results, failed, invalid, duplicate, not_read.
status_detailWhy, in words, when the status is not ok.
scraped_atWhen the run read this row (UTC).
job_idLinkedIn's job id (the number in the job URL); the de-duplication key.
urlThe job on LinkedIn: https://www.linkedin.com/jobs/view/
url_slugThe job's own slug URL (…/jobs/view/
titleThe job title as the posting states it.
company_nameThe company as the posting names it.
company_urlThe company's LinkedIn page (https://www.linkedin.com/company/
company_slugThe company's LinkedIn slug (the key of the company facts).
company_logo_urlThe company's logo as the card loads it (media.licdn.com).
locationThe job's location as LinkedIn shows it ("Austin, TX", "Saarbrücken, Saarland, Germany").
posted_dateThe posting day from the card's own <time datetime> (YYYY-MM-DD); for a job asked by id, the day of posted_at under includeExpiry, else null. Never computed from "2 weeks ago".
posted_agoThe relative text as LinkedIn shows it ("2 weeks ago").
posted_atThe posting time to the second (LinkedIn's JSON-LD datePosted), with includeExpiry; else null.
expires_atLinkedIn's expiry time for the posting (JSON-LD validThrough), with includeExpiry; else null.
applicants_textThe applicants text as the page shows it ("Be among the first 25 applicants", "Over 200 applicants", "57 applicants").
applicants_minThe floor the text implies: 0 for "first 25", 201 for "Over 200", 57 for "57 applicants".
applicants_maxThe ceiling the text implies: 24 for "first 25", 57 for "57 applicants"; null for "Over 200" (open).
salary_textLinkedIn's own salary block on the posting ("$60.00/hr - $100.00/hr") or the card's salary text; null when LinkedIn shows none. Never parsed out of the description.
salary_minThe lower amount of salary_text.
salary_maxThe upper amount of salary_text (the same as the minimum for a single figure).
salary_currencyThe currency of salary_text by its symbol (USD, EUR, GBP, …) or LinkedIn's JSON-LD currency.
salary_periodThe pay period of salary_text: hour, day, week, month or year.
seniority_levelLinkedIn's Seniority level (Internship, Entry level, Associate, Mid-Senior level, Director, Executive, Not Applicable). The job's full page gives it when the run reads that page (a search with experienceLevels, or includeExpiry); else the job's fragment, which says Not Applicable for many jobs whose full page names a level (5 of 8 on our test).
employment_typeThe page's own Employment type (Full-time, Part-time, Contract, Temporary, Volunteer, Internship, Other).
industriesThe page's Industries as a list ("A, B, and C" split; a single industry name with "and" in it is kept whole).
industries_textThe page's Industries text as shown.
workplace_typeRemote, Hybrid or On-site when the title or the location names it, or the description states it about this job ("this is a fully remote position", "work model: hybrid", "in the office three days a week"); a perk such as "work from home on Fridays" is not a statement. Null otherwise (LinkedIn's logged-out page carries no workplace field; never guessed).
apply_typeeasy_apply (LinkedIn's Easy Apply) or external (the employer's site), from the page's apply button; null on a closed job.
is_closedTrue when the page says "No longer accepting applications" (the posting is still delivered).
has_hiring_teamTrue when the page shows a "message the job poster" block; the person is never read.
card_badgeThe card's badge as LinkedIn shows it ("Actively Hiring", "Be an early applicant"); null without one.
description_htmlThe posting's description as LinkedIn's HTML, whole.
description_textThe posting's description as text with its line breaks, whole.
details_readTrue when the job's page was read (the posting's fields are on the row); false for a card row.
rankThe job's place in LinkedIn's list as the search read it (1 = LinkedIn's first card; a card dropped by a filter or the criteria check keeps its place empty, and past the first date window the places go on counting); null for a job asked by URL or id.
company_idLinkedIn's numeric company id (from the company's page).
company_page_nameThe company's name on its own LinkedIn page.
company_websiteThe company's website from its LinkedIn page.
company_industryThe company's industry from its LinkedIn page.
company_sizeThe company's size as LinkedIn shows it ("201-500 employees").
company_employees_minThe lower bound of company_size.
company_employees_maxThe upper bound of company_size; null for "10,001+".
company_headquartersThe company's headquarters from its LinkedIn page.
company_typeThe company's type from its LinkedIn page (Public Company, Privately Held, …).
company_foundedThe founding year from the company's LinkedIn page.
company_specialtiesThe company's specialties as a list.
company_followersThe company's LinkedIn followers.
company_employees_on_linkedinHow many employees LinkedIn counts on the company's page.
company_taglineThe company's tagline from its LinkedIn page.
company_descriptionThe company's About text from its LinkedIn page.
company_details_readTrue when the company's page was read (or served from our week-long cache); false when includeCompanyDetails is off or the page was not served.
first_seen_atWith onlyNewJobs: the day this memory first saw the job.
last_seen_atWith onlyNewJobs: the day this memory last saw the job.
times_seenWith onlyNewJobs: how many runs of this memory saw the job.
search_keywordsA search row: the keywords sent to LinkedIn.
search_locationA search row: the location sent to LinkedIn.
search_urlA search row: the LinkedIn search URL given, when one was.
filtersA search row: the URL filters sent to LinkedIn (f_TPR, f_C, f_AL, f_EA, geoId, distance).
criteriaA search row: the experience / employment / workplace asks checked on each job's page.
header_textA search row: what LinkedIn searched, from the page's own header after its count ("Python Jobs in United States"; the count itself is count_text).
count_textA search row: LinkedIn's own count as shown ("11,000+", "22").
countA search row: count_text as a number.
count_is_floorA search row: true when LinkedIn's count ends in "+" (a floor, not an exact count).
windows_readA search row: one entry per slice read (the search's own window, then each deepSearch window): its count, calls, served (the distinct ids the window served, to check against its count), cards (those new to the search) and how it stopped (end, limit, cap, budget).
list_callsA search row: the search page and list calls made.
jobs_foundA search row: the distinct jobs read from LinkedIn's list.
jobs_deliveredA search row: the job rows delivered for this search.
duplicates_skippedA search row: jobs already delivered by an earlier search of this run (delivered once, with that search).
filtered_by_textA search row: cards dropped by titleInclude / titleExclude / companyExclude (no page read, free).
dropped_by_criteriaA search row: jobs whose page did not match experienceLevels / employmentTypes / workplaceTypes (free).
skipped_seenA search row: jobs an earlier run of this memory delivered (onlyNewJobs; free).
failed_detailsA search row: jobs whose page could not be read (free).
verdictA search row: COMPLETE (every job of an exact count, or the list's own end), TRUNCATED (LinkedIn's list ends at 1,000 a search while its count says more), CAPPED (your maxItemsPerSearch / maxItems / charge limit), PARTIAL (a refusal, an error or the time limit stopped the walk).
verdict_detailA search row: the verdict's numbers and reason in words.

Example record:

{
"row_type": "job",
"search_id": "s1",
"search_label": "python",
"input_id": "t2",
"status": "ok",
"status_detail": null,
"scraped_at": "2026-10-19T21:45:36Z",
"job_id": "4465379983",
"url": "https://www.linkedin.com/jobs/view/4465379983",
"url_slug": "https://www.linkedin.com/jobs/view/senior-software-engineer-python-at-venmo-4465379983",
"title": "Senior Software Engineer - Python",
"company_name": "Venmo",
"company_url": "https://www.linkedin.com/company/venmo",
"company_slug": "venmo",
"company_logo_url": "https://media.licdn.com/dms/image/v2/C560BAQFqYO6c_JfA5A/company-logo_100_100/company-logo_100_100/0/1630671648627/venmo_logo?e=2147483647&v=beta&t=Fi0eAWLUnQZSiwbMnfpJ8zsELjGcPFfJpi38G0DEBK8",
"location": "Austin, TX",
"posted_date": "2026-10-01",
"posted_ago": "2 weeks ago",
"posted_at": null,
"expires_at": null,
"applicants_text": "Over 200 applicants",
"applicants_min": 201,
"applicants_max": null,
"salary_text": null,
"salary_min": null,
"salary_max": null,
"salary_currency": null,
"salary_period": null,
"seniority_level": "Not Applicable",
"employment_type": "Full-time",
"industries": [
"Financial Services"
],
"industries_text": "Financial Services",
"workplace_type": "Hybrid",
"apply_type": "external",
"is_closed": false,
"has_hiring_team": false,
"card_badge": null,
"description_html": "<strong>The Company<br></strong>PayPal has been revolutionizing commerce globally for more than 25 years. Creating innovative experiences that make moving money, selling, and shopping simple, personalized, and secure, PayPal empowers consumers and businesses in approximately 200 markets to join and thrive in the global economy.<br><br>We operate a global, two-sided network at scale that connects hundreds of millions of merchants and consumers. We help merchants and consumers connect, transact, and complete payments, whether they are online or in person. PayPal is more than a connection to third-party payment networks. We provide proprietary payment solutions accepted by merchants that enable the completion of payments on our platform on behalf of our customers.<br><br>We offer our customers the flexibility to use their accounts to purchase and receive payments for goods and services, as well as the ability to transfer and withdraw funds. We enable consumers to exchange funds more safely with merchants using a variety of funding sources, which may include a bank account, a PayPal or Venmo account balance, PayPal and Venmo branded credit products, a credit card, a debit card, certain cryptocurrencies, or other stored value products such as gift cards, and eligible credit card rewards. Our PayPal, Venmo, and Xoom products also make it safer and simpler for friends and family to transfer funds to each other. We offer merchants an end-to-end payments solution that provides authorization and settlement capabilities, as well as instant access to funds and payouts. We also help merchants connect with their customers, process exchanges and returns, and manage risk. We enable consumers to engage in cross-border shopping and merchants to extend their global reach while reducing the complexity and friction involved in enabling cross-border trade.<br><br>Our beliefs are the foundation for how we conduct business every day. We live each day guided by our core values of Inclusion, Innovation, Collaboration, and Wellness. Together, our values ensure that we work together as one global team with our customers at the center of everything we do – and they push us to ensure we take care of ourselves, each other, and our communities.<br><br><strong>Job Summary:<br><br></strong>As a Backend Engineer on the Venmo Identity Engineering team, you will develop secure, scalable backend solutions that enable authentication and authorization for millions of customers. You’ll write clean, efficient code, collaborate with experienced engineers, and contribute to building high-performance systems that enhance customer trust and experience. This role is ideal for engineers eager to grow their technical expertise while working on mission-critical identity services.<br><br><strong>Job Description:<br><br></strong><strong>Essential Responsibilities: <br><br></strong><ul><li>Delivers complete solutions spanning all phases of the Software Development Lifecycle (SDLC) (design, implementation, testing, delivery and operations), based on definitions from more senior roles.</li><li>Advises immediate management on project-level issues</li><li>Guides junior engineers</li><li>Operates with little day-to-day supervision, making technical decisions based on knowledge of internal conventions and industry best practices</li><li>Applies knowledge of technical best practices in making decisions<br><br></li></ul><strong>Expected Qualifications:<br><br></strong><ul><li>3+ years relevant experience and a Bachelor’s degree OR Any equivalent combination of education and experience.<br><br></li></ul><strong>Additional Responsibilities &amp; Preferred Qualifications:<br><br></strong><strong>Additional Qualifications<br></strong><ul><li>Strong foundation in programming concepts and data structures.</li><li>Experience with backend development using Python and frameworks such as Django or Flask.</li><li>Understanding of web services and Service-Oriented Architecture (SOA) principles.</li><li>Exposure to version control systems (e.g., Git) and collaborative development workflows.<br><br></li></ul><strong>Preferred Qualifications<br></strong><ul><li>Interest in large-scale, high-performance distributed systems.</li><li>Exposure to cloud platforms such as AWS, GCP, or Azure and Infrastructure as Code (Terraform).</li><li>Hands-on experience with databases (SQL and/or NoSQL).</li><li>Hands-on experience with low-latency in-memory databases such as Redis.</li><li>Hands-on experience with event-driven architecture and messaging systems such as SQS/SNS/Kafka/RabbitMQ/Pulsar.</li><li>Experience implementing CI/CD, automated testing, and observability to improve delivery quality and operational resilience.</li><li>Contributions to open-source projects or participation in developer communities.</li><li>Awareness of the payment processing industry and related compliance or regulatory standards.<br><br></li></ul><strong>Subsidiary:<br><br></strong>Venmo<br><br><strong>Travel Percent:<br><br></strong>0<br><br>Visa Sponsorship through PayPal is not available for this position now or any time in the future.<br><br>The base pay for this role will depend on where you work and the relevant experience and expertise you bring. The expected range of pay for this role by location is:<br><br><strong>Primary Location : Pay Range:<br><br></strong>San Jose, California: ($143,500.00 - $212,850.00 Annually)<br><br><strong>Additional Location(s) : Pay Range:<br><br></strong>Austin, Texas: ($130,500.00 - $193,600.00 Annually)<br><br>Additional compensation for this role may include an annual performance bonus, equity, or other incentive compensation, as applicable.<br><br>PayPal does not charge candidates any fees for courses, applications, resume reviews, interviews, background checks, or onboarding. When making an application directly, we will never ask you to share passwords, one-time passcodes (OTP), or verification codes. Any such request is a red flag and likely part of a scam. All communication regarding your application will come from official PayPal email domains. If you suspect fraudulent activity, please report it immediately. To learn more about how to identify and avoid recruitment fraud please visit https://careers.pypl.com/contact-us.<br><br>For the majority of employees, PayPal's balanced hybrid work model offers 3 days in the office for effective in-person collaboration and 2 days at your choice of either the PayPal office or your home workspace, ensuring that you equally have the benefits and conveniences of both locations.<br><br><strong>Our Benefits:<br><br></strong>At PayPal, we’re committed to building an equitable and inclusive global economy. And we can’t do this without our most important asset-you. That’s why we offer comprehensive, choice-based programs, to support all aspects of personal wellbeing—physical, emotional, and financial—delivering meaningful value where it matters most. We strive to create a flexible, balanced work culture with a holistic approach to benefits, including generous paid time off, healthcare coverage for you and your family, and resources to create financial security and support your mental health.<br><br><strong>Who We Are:<br><br></strong>Click Here to learn more about our culture and community.<br><br><strong>Commitment to Diversity and Inclusion <br><br></strong>PayPal provides equal employment opportunity (EEO) to all persons regardless of age, color, national origin, citizenship status, physical or mental disability, race, religion, creed, gender, sex, pregnancy, sexual orientation, gender identity and/or expression, genetic information, marital status, status with regard to public assistance, veteran status, or any other characteristic protected by federal, state, or local law. In addition, PayPal will provide reasonable accommodations for qualified individuals with disabilities. If you are unable to submit an application because of incompatible assistive technology or a disability, please contact us at paypalglobaltalentacquisition@paypal.com.<br><br><strong>Belonging at PayPal:<br><br></strong>Our employees are central to advancing our mission, and we strive to create an environment where everyone can do their best work with a sense of purpose and belonging. Belonging at PayPal means creating a workplace with a sense of acceptance and security where all employees feel included and valued. We are proud to have a diverse workforce reflective of the merchants, consumers, and communities that we serve, and we continue to take tangible actions to cultivate inclusivity and belonging at PayPal.<br><br>Any general requests for consideration of your skills, please Join our Talent Community.<br><br>We know the confidence gap and imposter syndrome can get in the way of meeting spectacular candidates. Please don’t hesitate to apply.",
"description_text": "The Company\nPayPal has been revolutionizing commerce globally for more than 25 years. Creating innovative experiences that make moving money, selling, and shopping simple, personalized, and secure, PayPal empowers consumers and businesses in approximately 200 markets to join and thrive in the global economy.\n\nWe operate a global, two-sided network at scale that connects hundreds of millions of merchants and consumers. We help merchants and consumers connect, transact, and complete payments, whether they are online or in person. PayPal is more than a connection to third-party payment networks. We provide proprietary payment solutions accepted by merchants that enable the completion of payments on our platform on behalf of our customers.\n\nWe offer our customers the flexibility to use their accounts to purchase and receive payments for goods and services, as well as the ability to transfer and withdraw funds. We enable consumers to exchange funds more safely with merchants using a variety of funding sources, which may include a bank account, a PayPal or Venmo account balance, PayPal and Venmo branded credit products, a credit card, a debit card, certain cryptocurrencies, or other stored value products such as gift cards, and eligible credit card rewards. Our PayPal, Venmo, and Xoom products also make it safer and simpler for friends and family to transfer funds to each other. We offer merchants an end-to-end payments solution that provides authorization and settlement capabilities, as well as instant access to funds and payouts. We also help merchants connect with their customers, process exchanges and returns, and manage risk. We enable consumers to engage in cross-border shopping and merchants to extend their global reach while reducing the complexity and friction involved in enabling cross-border trade.\n\nOur beliefs are the foundation for how we conduct business every day. We live each day guided by our core values of Inclusion, Innovation, Collaboration, and Wellness. Together, our values ensure that we work together as one global team with our customers at the center of everything we do – and they push us to ensure we take care of ourselves, each other, and our communities.\n\nJob Summary:\n\nAs a Backend Engineer on the Venmo Identity Engineering team, you will develop secure, scalable backend solutions that enable authentication and authorization for millions of customers. You’ll write clean, efficient code, collaborate with experienced engineers, and contribute to building high-performance systems that enhance customer trust and experience. This role is ideal for engineers eager to grow their technical expertise while working on mission-critical identity services.\n\nJob Description:\n\nEssential Responsibilities:\n\nDelivers complete solutions spanning all phases of the Software Development Lifecycle (SDLC) (design, implementation, testing, delivery and operations), based on definitions from more senior roles.\nAdvises immediate management on project-level issues\nGuides junior engineers\nOperates with little day-to-day supervision, making technical decisions based on knowledge of internal conventions and industry best practices\nApplies knowledge of technical best practices in making decisions\n\nExpected Qualifications:\n\n3+ years relevant experience and a Bachelor’s degree OR Any equivalent combination of education and experience.\n\nAdditional Responsibilities & Preferred Qualifications:\n\nAdditional Qualifications\nStrong foundation in programming concepts and data structures.\nExperience with backend development using Python and frameworks such as Django or Flask.\nUnderstanding of web services and Service-Oriented Architecture (SOA) principles.\nExposure to version control systems (e.g., Git) and collaborative development workflows.\n\nPreferred Qualifications\nInterest in large-scale, high-performance distributed systems.\nExposure to cloud platforms such as AWS, GCP, or Azure and Infrastructure as Code (Terraform).\nHands-on experience with databases (SQL and/or NoSQL).\nHands-on experience with low-latency in-memory databases such as Redis.\nHands-on experience with event-driven architecture and messaging systems such as SQS/SNS/Kafka/RabbitMQ/Pulsar.\nExperience implementing CI/CD, automated testing, and observability to improve delivery quality and operational resilience.\nContributions to open-source projects or participation in developer communities.\nAwareness of the payment processing industry and related compliance or regulatory standards.\n\nSubsidiary:\n\nVenmo\n\nTravel Percent:\n\n0\n\nVisa Sponsorship through PayPal is not available for this position now or any time in the future.\n\nThe base pay for this role will depend on where you work and the relevant experience and expertise you bring. The expected range of pay for this role by location is:\n\nPrimary Location : Pay Range:\n\nSan Jose, California: ($143,500.00 - $212,850.00 Annually)\n\nAdditional Location(s) : Pay Range:\n\nAustin, Texas: ($130,500.00 - $193,600.00 Annually)\n\nAdditional compensation for this role may include an annual performance bonus, equity, or other incentive compensation, as applicable.\n\nPayPal does not charge candidates any fees for courses, applications, resume reviews, interviews, background checks, or onboarding. When making an application directly, we will never ask you to share passwords, one-time passcodes (OTP), or verification codes. Any such request is a red flag and likely part of a scam. All communication regarding your application will come from official PayPal email domains. If you suspect fraudulent activity, please report it immediately. To learn more about how to identify and avoid recruitment fraud please visit https://careers.pypl.com/contact-us.\n\nFor the majority of employees, PayPal's balanced hybrid work model offers 3 days in the office for effective in-person collaboration and 2 days at your choice of either the PayPal office or your home workspace, ensuring that you equally have the benefits and conveniences of both locations.\n\nOur Benefits:\n\nAt PayPal, we’re committed to building an equitable and inclusive global economy. And we can’t do this without our most important asset-you. That’s why we offer comprehensive, choice-based programs, to support all aspects of personal wellbeing—physical, emotional, and financial—delivering meaningful value where it matters most. We strive to create a flexible, balanced work culture with a holistic approach to benefits, including generous paid time off, healthcare coverage for you and your family, and resources to create financial security and support your mental health.\n\nWho We Are:\n\nClick Here to learn more about our culture and community.\n\nCommitment to Diversity and Inclusion\n\nPayPal provides equal employment opportunity (EEO) to all persons regardless of age, color, national origin, citizenship status, physical or mental disability, race, religion, creed, gender, sex, pregnancy, sexual orientation, gender identity and/or expression, genetic information, marital status, status with regard to public assistance, veteran status, or any other characteristic protected by federal, state, or local law. In addition, PayPal will provide reasonable accommodations for qualified individuals with disabilities. If you are unable to submit an application because of incompatible assistive technology or a disability, please contact us at paypalglobaltalentacquisition@paypal.com.\n\nBelonging at PayPal:\n\nOur employees are central to advancing our mission, and we strive to create an environment where everyone can do their best work with a sense of purpose and belonging. Belonging at PayPal means creating a workplace with a sense of acceptance and security where all employees feel included and valued. We are proud to have a diverse workforce reflective of the merchants, consumers, and communities that we serve, and we continue to take tangible actions to cultivate inclusivity and belonging at PayPal.\n\nAny general requests for consideration of your skills, please Join our Talent Community.\n\nWe know the confidence gap and imposter syndrome can get in the way of meeting spectacular candidates. Please don’t hesitate to apply.",
"details_read": true,
"rank": 1,
"company_id": "552278",
"company_page_name": "Venmo",
"company_website": "http://www.venmo.com",
"company_industry": "Financial Services",
"company_size": "201-500 employees",
"company_employees_min": 201,
"company_employees_max": 500,
"company_headquarters": "New York, NY",
"company_type": "Public Company",
"company_founded": null,
"company_specialties": [
"Mobile Payments",
"Social Payments",
"Convenient Payments",
"Text Message Payments",
"FinTech",
"P2P Payments",
"App"
],
"company_followers": 69617,
"company_employees_on_linkedin": 713,
"company_tagline": null,
"company_description": "At Venmo, we’re working to build a payment experience that's simple, delightful and connected. Since our founding in 2009, we’ve quickly grown from an idea hatched by two college roommates who wanted a better way to pay each other back to the go-to digital wallet that’s known and loved by millions. What started off as a simple SMS platform to send and receive money has evolved into a social payments app allowing people to pay, split and share their experiences.",
"company_details_read": true,
"first_seen_at": null,
"last_seen_at": null,
"times_seen": null,
"search_keywords": "python",
"search_location": "United States",
"search_url": null,
"filters": null,
"criteria": null,
"header_text": null,
"count_text": null,
"count": null,
"count_is_floor": null,
"windows_read": null,
"list_calls": null,
"jobs_found": null,
"jobs_delivered": null,
"duplicates_skipped": null,
"filtered_by_text": null,
"dropped_by_criteria": null,
"skipped_seen": null,
"failed_details": null,
"verdict": null,
"verdict_detail": null
}

Pricing

Pay for the jobs a run delivers, plus one run start; no platform usage is billed to you. The row prices fall with your Apify plan.

eventunitFreeStarterScaleBusiness
Job (job)per 1,000$2.00$1.00$1.00$1.00
Card row (search cards only) (card)per 1,000$0.10$0.085$0.07$0.066
Run start (start)per run$0.00177$0.00177$0.00177$0.00177

A job with its full posting and the company's facts is $2.00 per 1,000 on the Free plan ($0.002 a job) and $1.00 on every paid plan. A card row (the search's cards alone, includeJobDetails off) is $0.10 per 1,000 on Free. Each run that delivers a charged row also pays the run start, $0.00177 once; a run that delivers no charged row pays nothing at all. So 100 jobs cost $0.20177 on the Free plan and $0.10177 on a paid plan; 1,000 jobs $2.00177 and $1.00177; several searches in one run share one start. An experience, job type or workplace check costs nothing extra: a job that does not match is dropped before it is charged. Free: every search summary row (LinkedIn's count, the windows, the counts and the verdict), a job LinkedIn has no page for (not_found), a value that is no job or search (invalid), a repeated input or a job already delivered in the run (duplicate), an input left unread at the cap or the time limit (not_read), a job page that could not be read (failed), a card dropped by titleInclude / titleExclude / companyExclude or by a check, and a job an earlier run of the same onlyNewJobs memory delivered. The company's facts and the expiry page are inside the job price. A job is charged once a run whatever searches overlap; a run that stops early (a timeout, an abort) is charged for the rows it delivered. maxItems counts the charged rows. Before the first request the log names the price of each row at your plan, the run start and the most the run can cost: a search without maxItemsPerSearch is read to LinkedIn's own count, at most 1,000 jobs a search (6,000 with deepSearch), so set maxItems, maxItemsPerSearch or a charge limit for a lower maximum. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.

Usage patterns

  • One search or many — Give keywords and location (and the filters) for one search, or list searches in searches: strings (keywords, or a LinkedIn jobs search URL whose own parameters apply) or objects with their own keywords, location, url, filters, maxItemsPerSearch and id. The run's own fields are the defaults of every item. Every row carries search_id, search_label and your input_id; every search gets one free search row with LinkedIn's count, the header LinkedIn searched ("Python Jobs in Germany"), the pages and windows read, the counts and the verdict. Nothing at all given = LinkedIn's blank search (every job, in the worker's country).
  • What a row is — row_type = job: one job, in LinkedIn's order (rank 1…); with includeJobDetails (the default) the posting's fields are on it and details_read is true (charged as a job); with includeJobDetails off the card's fields alone (id, URL, title, company, location, posted date and text, salary text, badge, logo; charged as a card row). row_type = search: the free summary of a search — count_text and count with count_is_floor ("11,000+" is a floor), header_text, windows_read, list_calls, jobs_found, jobs_delivered, duplicates_skipped, filtered_by_text, dropped_by_criteria, skipped_seen, failed_details, the verdict with its verdict_detail, and the status with its reason.
  • How far a search goes — maxItemsPerSearch = 0 (the default) reads every job LinkedIn lists for the search, in its order: the public page's 60 cards, then the guest list ten cards a call to its end — an empty page read twice, or LinkedIn's own cap at 1,000 a search (verdict TRUNCATED with the count). deepSearch then reads the nested date windows (30 d, 7 d, 24 h, 6 h, 1 h), each a slice of up to 1,000 more, every job once; a window's list is not date-ordered on LinkedIn's side, so the union is what the public route reaches and the verdict stays TRUNCATED with every window's numbers. An exact count under 1,000 ("22 Python Jobs in Boise") ends COMPLETE. maxItems caps the charged rows of the whole run; a search left unread at the cap gets a free not_read row.
  • Filters — Applied by LinkedIn itself: datePosted (24h / week / month) or postedWithinSeconds (any window), companyIds (ids, company URLs or slugs), easyApplyOnly, under10ApplicantsOnly, geoId with distance. Checked on each job's page, because LinkedIn's logged-out search ignores its own filters for them: experienceLevels (the page's Seniority level), employmentTypes (Employment type), workplaceTypes (the title or location's word, or a statement about the job in its description; a work-from-home perk is not one; a posting that states none is dropped, never guessed). A dropped job is never charged. These checks need includeJobDetails on, and a rare value stops the search at a read budget: after its first 20 job pages, at most 7 pages a delivered row, the summary row saying how many pages matched (narrow the keywords, the place or the date window to reach more). titleInclude, titleExclude and companyExclude apply on the card before any page is read. A sort by date is not offered: LinkedIn's logged-out list ignores sortBy; use a date window and the card's posted_date.
  • A job by URL or id, the expiry date and the exact time — jobUrls takes LinkedIn job URLs (with or without the slug) and bare ids: each gets its posting and the company's facts; an unknown id is a free not_found row. includeExpiry reads each job's full page instead of the fragment (about four times the bytes): expires_at is LinkedIn's validThrough and posted_at the posting time to the second (the card gives the day only; a job asked by id has no card, so its posted_date comes from posted_at under includeExpiry, else null). A job already delivered by a search of the same run is a free duplicate row.
  • Scheduled runs: only the new jobs — Save a task with onlyNewJobs (and a stateStoreName to name the memory) and schedule it: a job delivered by an earlier run of that memory is skipped free, and first_seen_at, last_seen_at and times_seen ride every delivered row. Or set postedWithinSeconds to the task's interval (3600 for an hourly task): LinkedIn's own date window serves only the postings since.

Input configuration

fieldtypedefaultwhat it does
keywordsstring""What to search for, as you would type it on LinkedIn Jobs (python developer, "data engineer"). Empty with everything else empty = LinkedIn's blank search (every job, newest first, in the location or the worker's country). A word LinkedIn cannot match is served by LinkedIn as the location's whole list with the word echoed in the summary row's header_text: use titleInclude to keep only the titles you mean.
locationstring""A city, a region or a country as LinkedIn names it (United States, Austin, Texas, Germany). LinkedIn resolves it; the summary row's header_text shows what it searched ("Python Jobs in Germany"). Beside a searches list it is the list's default location.
searchesarray[]Several searches in one run (at most 100). Each item is a string (keywords, or a LinkedIn jobs search URL: its keywords, location, geoId, distance, f_TPR, f_C, f_AL and f_EA apply, f_E / f_JT / f_WT become the criteria checks, sortBy is left out) or an object with keywords, location, url, geoId, distance, datePosted, postedWithinSeconds, companyIds, easyApplyOnly, under10ApplicantsOnly, experienceLevels, employmentTypes, workplaceTypes, titleInclude, titleExclude, companyExclude, maxItemsPerSearch and your own id (carried on every row of that search as input_id). The run's own fields are the defaults of every item.
jobUrlsarray[]Jobs to read one by one: a LinkedIn job URL (https://www.linkedin.com/jobs/view/
datePosted`` / 24h / week / month""LinkedIn's own date filter (f_TPR), applied by LinkedIn: every row's posted_date lies inside the window. For any other window use postedWithinSeconds.
postedWithinSecondsinteger0Any date window in seconds (3600 = the past hour, 172800 = two days): LinkedIn's f_TPR=r
companyIdsarray[]Only jobs of these companies: LinkedIn company ids (1441 = Google), company URLs (https://www.linkedin.com/company/google) or slugs; a URL or slug is read to its id on the company's public page first (LinkedIn's search takes ids only), and one whose page gives no id is a free invalid search row. Several = any of them (LinkedIn's f_C filter, applied by LinkedIn).
easyApplyOnlybooleanfalseOnly jobs with LinkedIn's Easy Apply (f_AL=true, applied by LinkedIn). Off: every job, with apply_type saying easy_apply or external on each.
under10ApplicantsOnlybooleanfalseOnly jobs with fewer than 10 applicants (LinkedIn's f_EA filter, applied by LinkedIn).
geoIdstring""LinkedIn's own place id from a LinkedIn jobs search URL (geoId=90000064 is Austin, Texas); with distance it replaces location. Leave empty to search by location.
distanceinteger0A radius in miles around the geoId or the location (LinkedIn's distance filter, applied by LinkedIn). 0 = LinkedIn's default.
experienceLevelsarray[]Internship, Entry level, Associate, Mid-Senior level, Director, Executive. LinkedIn's logged-out search ignores its experience filter, so each job's full page is read and its Seniority level checked (the job's fragment says Not Applicable for many jobs whose page names a level): a job that does not match is dropped free before it is charged, and the summary row counts the drops (dropped_by_criteria). A rare level stops the search at a read budget (after the first 20 job pages, at most 7 pages a delivered row; the summary row says so). Needs includeJobDetails on. Empty = every level.
employmentTypesarray[]Full-time, Part-time, Contract, Temporary, Volunteer, Internship, Other. Checked on each job's page (its Employment type), a miss dropped free, with the same read budget as experienceLevels. Needs includeJobDetails on. Empty = every type.
workplaceTypesarray[]Remote, Hybrid, On-site. LinkedIn's logged-out pages carry no workplace field, so the posting decides: its title or location ("(Remote)", "(Hybrid)") or a statement about this job in its description ("a fully remote position", "work model: hybrid", "three days a week in the office"); a perk such as "work from home on Fridays" is not one, and a posting that states none is dropped free, never guessed. Same read budget as experienceLevels; needs includeJobDetails on. Empty = every job, with workplace_type the posting's own statement or null.
titleIncludearray[]Keep only jobs whose title contains one of these words (case-insensitive), checked on the search card before any page is read. Empty = every title.
titleExcludearray[]Drop jobs whose title contains one of these words (case-insensitive), checked on the search card. Empty = nothing dropped.
companyExcludearray[]Drop jobs whose company name contains one of these words (case-insensitive), checked on the search card. Empty = nothing dropped.
maxItemsPerSearchinteger0How many jobs each search delivers at most, in LinkedIn's order. 0 = every job LinkedIn lists for the search: up to 1,000 (LinkedIn's own cap per search), and past it the date windows of deepSearch. An item of searches may carry its own.
deepSearchbooleanfalseWhen a search's count is a floor ("11,000+") and its list ends at LinkedIn's 1,000, read it again inside nested date windows (past 30 days, 7 days, 24 hours, 6 hours, 1 hour), each a slice of up to 1,000 more, every job once. The summary row names each window's count and what it added. More rows and calls: up to 6 slices per search.
includeJobDetailsbooleantrueOn: each job's page is read (one call): the description as HTML and text, seniority, employment type, industries, the applicants text, the salary block, the apply type, the closed flag; the row is charged as a job. Off: the search cards alone (id, URL, title, company, location, date, salary text, badge): a cheaper card row, no page read. A job given in jobUrls always gets its posting. experienceLevels, employmentTypes and workplaceTypes are checked on the page, so they need this on.
includeCompanyDetailsbooleantrueThe company's public page once per company (website, industry, size, headquarters, type, founded, specialties, followers, description), on every row of that company at no extra charge.
includeExpirybooleanfalseRead each job's full page instead of its fragment (about four times the bytes): expires_at (LinkedIn's validThrough) and posted_at (the posting time to the second). Needs includeJobDetails on.
onlyNewJobsbooleanfalseRemember every job delivered under this memory (stateStoreName, or a name derived from the searches) and skip it free in the next run: a scheduled task delivers only what is new. The summary row counts the skipped (skipped_seen).
stateStoreNamestring""The name of the onlyNewJobs memory, so several tasks can share one or keep theirs apart. Empty: a name derived from the searches.
maxItemsinteger0The most charged rows the run delivers over every search and job (summary rows and free rows do not count). 0 = no limit beyond maxItemsPerSearch and LinkedIn's own ends. The log names the most the run can cost before the first request.
maxConcurrencyinteger4How many LinkedIn sessions read at once, one call a second each. 4 by default: about 85 jobs a minute with the postings (780 of a 944-job search in 9 minutes on our test, so a whole 1,000-job search takes about 12 minutes); 8 read about 145 jobs a minute on two test runs; 1 for a gentle run.
proxyUrlstringEmpty (recommended): LinkedIn is read through the Actor's own exits at no extra cost to you. Your own proxy URL (scheme://user:pass@host:port) carries every call instead. The word none runs without any proxy, from the Apify worker's own IP (for tests).

Errors

A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:

  • the status message starts with INPUT REJECTED;
  • the dataset holds one row, {"error": true, "code": "…", "message": "…"}, and no results;
  • the key-value store record ERROR holds the same object.

From code, check error on the first row before reading results.

A search LinkedIn lists no job for is not an error: it gets one free search row with status no_results, and the run goes on with the others. A keyword LinkedIn cannot match is served by LinkedIn itself as the location's whole list with the word echoed in the row's header_text ("Zzqxvwxq9k Jobs in United States"): use titleInclude to keep only the titles you mean. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.

FAQ

How many jobs does a search return?

As many as you ask (maxItemsPerSearch), up to every job LinkedIn lists logged out: 1,000 a search (LinkedIn answers HTTP 400 past start=1000), and with deepSearch up to five more slices of 1,000 by date window. A search with an exact count under 1,000 comes back whole (COMPLETE). The summary row says how many LinkedIn counts ("11,000+" is a floor LinkedIn itself gives) against what was read, so a short dataset is never silent. Splitting a search by city, company or date window yourself (several items in searches) reaches more; every job is delivered once a run.

Why are experience level, job type and workplace checked on the page and not in the search?

Because LinkedIn's logged-out search ignores those three URL filters: on our study 10 of 10 filtered pages were identical to the unfiltered control, for every value. Tools that pass the filter through deliver the unfiltered list. Here each job's page is read and its own Seniority level, Employment type or workplace words decide; a job that does not match is dropped before it is charged, and the summary row counts the drops. A search with a strict filter reads more pages than it delivers rows, so it has a read budget: after the first 20 job pages, at most 7 pages a delivered row; a rarer value stops the search TRUNCATED and its summary row says how many pages matched. The experience level is read from the job's full page, because the job's fragment says Not Applicable for many jobs whose page names a level.

Where are the apply URL, the job function and the skills?

Not on LinkedIn's logged-out pages: the employer's apply link sits behind LinkedIn's sign-in, the job function and the skills are served to logged-in members only (0 of 501 postings on our study; the full page's JSON-LD skills is filled on few postings: 1 of 7 on our test). Tools that show an apply URL logged out show the LinkedIn job URL or a sign-up redirect; this Actor never does. apply_type tells Easy Apply from an external apply, and url opens the job on LinkedIn.

Is the job poster's name on the row?

No. has_hiring_team says whether the page shows a "message the job poster" block; the person's name, title and profile are never read or stored. The company's facts are the company's public page.

Does it need a LinkedIn account, cookies or an API key?

No. Everything is read from LinkedIn's public job pages and their guest endpoints, logged out, with a plain HTTP client; nothing of yours is sent to LinkedIn. No member cookie is accepted and none is used.

Which status is which?

A search row's status is ok (jobs served), no_results (LinkedIn lists nothing), failed (a refusal or an error; free), invalid (a value that is no search), duplicate (the same search and filters given twice), or not_read (left at maxItems, the charge limit or the run's time limit). A job row's status is ok (charged; a closed job is ok with is_closed true), not_found (LinkedIn answers 404 for the id), failed (its page could not be read), invalid, duplicate (already delivered in this run) or not_read; the free ones carry status_detail.

Integration

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/linkedin-jobs-scraper').call({"keywords": "python", "location": "United States", "maxItemsPerSearch": 100});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/linkedin-jobs-scraper').call(run_input={'keywords': 'python', 'location': 'United States', 'maxItemsPerSearch': 100})
items = client.dataset(run['defaultDatasetId']).list_items().items

CLI

$apify call hyperbach/linkedin-jobs-scraper --input '{"keywords": "python", "location": "United States", "maxItemsPerSearch": 100}'

REST

curl -X POST "https://api.apify.com/v2/acts/hyperbach~linkedin-jobs-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' -d '{"keywords": "python", "location": "United States", "maxItemsPerSearch": 100}'

Support

apify@hyperbach.com

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.