LinkedIn Jobs Scraper & LinkedIn Jobs API: Job Postings Data
Pricing
from $1.00 / 1,000 jobs
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
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
3 days ago
Last modified
Categories
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_min0,applicants_max24; "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
searchrow 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).deepSearchgoes 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):
| field | meaning |
|---|---|
row_type | job (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_id | s1, s2, … in the order of the inputs: the search or job input this row answers. |
search_label | The input as you gave it (the keywords, the URL or the job id). |
input_id | Your own id from a search object, carried on every row it produces. |
status | A job row: ok (charged), not_found, failed, invalid, duplicate, not_read (free). A search row: ok, no_results, failed, invalid, duplicate, not_read. |
status_detail | Why, in words, when the status is not ok. |
scraped_at | When the run read this row (UTC). |
job_id | LinkedIn's job id (the number in the job URL); the de-duplication key. |
url | The job on LinkedIn: https://www.linkedin.com/jobs/view/ |
url_slug | The job's own slug URL (…/jobs/view/ |
title | The job title as the posting states it. |
company_name | The company as the posting names it. |
company_url | The company's LinkedIn page (https://www.linkedin.com/company/ |
company_slug | The company's LinkedIn slug (the key of the company facts). |
company_logo_url | The company's logo as the card loads it (media.licdn.com). |
location | The job's location as LinkedIn shows it ("Austin, TX", "Saarbrücken, Saarland, Germany"). |
posted_date | The 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_ago | The relative text as LinkedIn shows it ("2 weeks ago"). |
posted_at | The posting time to the second (LinkedIn's JSON-LD datePosted), with includeExpiry; else null. |
expires_at | LinkedIn's expiry time for the posting (JSON-LD validThrough), with includeExpiry; else null. |
applicants_text | The applicants text as the page shows it ("Be among the first 25 applicants", "Over 200 applicants", "57 applicants"). |
applicants_min | The floor the text implies: 0 for "first 25", 201 for "Over 200", 57 for "57 applicants". |
applicants_max | The ceiling the text implies: 24 for "first 25", 57 for "57 applicants"; null for "Over 200" (open). |
salary_text | LinkedIn'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_min | The lower amount of salary_text. |
salary_max | The upper amount of salary_text (the same as the minimum for a single figure). |
salary_currency | The currency of salary_text by its symbol (USD, EUR, GBP, …) or LinkedIn's JSON-LD currency. |
salary_period | The pay period of salary_text: hour, day, week, month or year. |
seniority_level | LinkedIn'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_type | The page's own Employment type (Full-time, Part-time, Contract, Temporary, Volunteer, Internship, Other). |
industries | The page's Industries as a list ("A, B, and C" split; a single industry name with "and" in it is kept whole). |
industries_text | The page's Industries text as shown. |
workplace_type | Remote, 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_type | easy_apply (LinkedIn's Easy Apply) or external (the employer's site), from the page's apply button; null on a closed job. |
is_closed | True when the page says "No longer accepting applications" (the posting is still delivered). |
has_hiring_team | True when the page shows a "message the job poster" block; the person is never read. |
card_badge | The card's badge as LinkedIn shows it ("Actively Hiring", "Be an early applicant"); null without one. |
description_html | The posting's description as LinkedIn's HTML, whole. |
description_text | The posting's description as text with its line breaks, whole. |
details_read | True when the job's page was read (the posting's fields are on the row); false for a card row. |
rank | The 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_id | LinkedIn's numeric company id (from the company's page). |
company_page_name | The company's name on its own LinkedIn page. |
company_website | The company's website from its LinkedIn page. |
company_industry | The company's industry from its LinkedIn page. |
company_size | The company's size as LinkedIn shows it ("201-500 employees"). |
company_employees_min | The lower bound of company_size. |
company_employees_max | The upper bound of company_size; null for "10,001+". |
company_headquarters | The company's headquarters from its LinkedIn page. |
company_type | The company's type from its LinkedIn page (Public Company, Privately Held, …). |
company_founded | The founding year from the company's LinkedIn page. |
company_specialties | The company's specialties as a list. |
company_followers | The company's LinkedIn followers. |
company_employees_on_linkedin | How many employees LinkedIn counts on the company's page. |
company_tagline | The company's tagline from its LinkedIn page. |
company_description | The company's About text from its LinkedIn page. |
company_details_read | True 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_at | With onlyNewJobs: the day this memory first saw the job. |
last_seen_at | With onlyNewJobs: the day this memory last saw the job. |
times_seen | With onlyNewJobs: how many runs of this memory saw the job. |
search_keywords | A search row: the keywords sent to LinkedIn. |
search_location | A search row: the location sent to LinkedIn. |
search_url | A search row: the LinkedIn search URL given, when one was. |
filters | A search row: the URL filters sent to LinkedIn (f_TPR, f_C, f_AL, f_EA, geoId, distance). |
criteria | A search row: the experience / employment / workplace asks checked on each job's page. |
header_text | A 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_text | A search row: LinkedIn's own count as shown ("11,000+", "22"). |
count | A search row: count_text as a number. |
count_is_floor | A search row: true when LinkedIn's count ends in "+" (a floor, not an exact count). |
windows_read | A 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_calls | A search row: the search page and list calls made. |
jobs_found | A search row: the distinct jobs read from LinkedIn's list. |
jobs_delivered | A search row: the job rows delivered for this search. |
duplicates_skipped | A search row: jobs already delivered by an earlier search of this run (delivered once, with that search). |
filtered_by_text | A search row: cards dropped by titleInclude / titleExclude / companyExclude (no page read, free). |
dropped_by_criteria | A search row: jobs whose page did not match experienceLevels / employmentTypes / workplaceTypes (free). |
skipped_seen | A search row: jobs an earlier run of this memory delivered (onlyNewJobs; free). |
failed_details | A search row: jobs whose page could not be read (free). |
verdict | A 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_detail | A 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 & 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.
| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
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
keywordsandlocation(and the filters) for one search, or list searches insearches: strings (keywords, or a LinkedIn jobs search URL whose own parameters apply) or objects with their own keywords, location, url, filters,maxItemsPerSearchandid. The run's own fields are the defaults of every item. Every row carriessearch_id,search_labeland yourinput_id; every search gets one freesearchrow 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 (rank1…); withincludeJobDetails(the default) the posting's fields are on it anddetails_readis true (charged as a job); withincludeJobDetailsoff 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_textandcountwithcount_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, theverdictwith itsverdict_detail, and thestatuswith 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 (verdictTRUNCATED with the count).deepSearchthen 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.maxItemscaps the charged rows of the whole run; a search left unread at the cap gets a freenot_readrow. - Filters — Applied by LinkedIn itself:
datePosted(24h / week / month) orpostedWithinSeconds(any window),companyIds(ids, company URLs or slugs),easyApplyOnly,under10ApplicantsOnly,geoIdwithdistance. 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 needincludeJobDetailson, 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,titleExcludeandcompanyExcludeapply 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'sposted_date. - A job by URL or id, the expiry date and the exact time —
jobUrlstakes 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 freenot_foundrow.includeExpiryreads each job's full page instead of the fragment (about four times the bytes):expires_atis LinkedIn's validThrough andposted_atthe posting time to the second (the card gives the day only; a job asked by id has no card, so itsposted_datecomes fromposted_atunderincludeExpiry, else null). A job already delivered by a search of the same run is a freeduplicaterow. - Scheduled runs: only the new jobs — Save a task with
onlyNewJobs(and astateStoreNameto name the memory) and schedule it: a job delivered by an earlier run of that memory is skipped free, andfirst_seen_at,last_seen_atandtimes_seenride every delivered row. Or setpostedWithinSecondsto the task's interval (3600 for an hourly task): LinkedIn's own date window serves only the postings since.
Input configuration
| field | type | default | what it does |
|---|---|---|---|
keywords | string | "" | 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. |
location | string | "" | 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. |
searches | array | [] | 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. |
jobUrls | array | [] | 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. |
postedWithinSeconds | integer | 0 | Any date window in seconds (3600 = the past hour, 172800 = two days): LinkedIn's f_TPR=r |
companyIds | array | [] | 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). |
easyApplyOnly | boolean | false | Only 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. |
under10ApplicantsOnly | boolean | false | Only jobs with fewer than 10 applicants (LinkedIn's f_EA filter, applied by LinkedIn). |
geoId | string | "" | 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. |
distance | integer | 0 | A radius in miles around the geoId or the location (LinkedIn's distance filter, applied by LinkedIn). 0 = LinkedIn's default. |
experienceLevels | array | [] | 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. |
employmentTypes | array | [] | 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. |
workplaceTypes | array | [] | 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. |
titleInclude | array | [] | 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. |
titleExclude | array | [] | Drop jobs whose title contains one of these words (case-insensitive), checked on the search card. Empty = nothing dropped. |
companyExclude | array | [] | Drop jobs whose company name contains one of these words (case-insensitive), checked on the search card. Empty = nothing dropped. |
maxItemsPerSearch | integer | 0 | How 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. |
deepSearch | boolean | false | When 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. |
includeJobDetails | boolean | true | On: 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. |
includeCompanyDetails | boolean | true | The 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. |
includeExpiry | boolean | false | Read 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. |
onlyNewJobs | boolean | false | Remember 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). |
stateStoreName | string | "" | The name of the onlyNewJobs memory, so several tasks can share one or keep theirs apart. Empty: a name derived from the searches. |
maxItems | integer | 0 | The 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. |
maxConcurrency | integer | 4 | How 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. |
proxyUrl | string | Empty (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
ERRORholds 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 ApifyClientclient = 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
This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.