50% OFF Residential Proxies for 9 months — use code IPR50 at checkout

Get The Deal

In This Article

Back to blog

LinkedIn Job Scraping With Python: A Step-by-Step Tutorial

Websites

Learn essential tools and techniques for effective LinkedIn job scraping. Enhance your job search strategy today.

Justas Vitaitis

Last updated - ‐ 7 min read

Key Takeaways

  • You can technically scrape job posting data on LinkedIn with Python, but it requires handling dynamic content and rate limits.

  • Both custom scripts and API solutions offer ways to collect job data, but each has its tradeoffs.

  • Always respect legal and ethical boundaries when scraping LinkedIn data.

Scraping LinkedIn job listings is a practical way to gather real-world hiring data for research, lead generation , competitive analysis, and more. While it’s powerful, it requires careful planning and understanding of both technical and legal sides.

We’ll walk you through the most essential parts of job scraping: from setup to legal considerations to exporting usable data.

Is It Possible (and Legal) to Scrape Jobs From LinkedIn?

Yes, it’s possible to scrape LinkedIn job postings using Python or even no-code scraping tools. LinkedIn, however, makes it hard and continuously implements new and more advanced anti-scraping measures.

Their servers detect automated behaviors quickly. They use rate limits, analyze your user-agent, and do a whole lot of other things that may ban your IP if you’re caught.

LinkedIn job listings often load content dynamically via JavaScript. Scraping them can require either a headless browser like Selenium or reproducing the underlying network/XHR requests used by the site to fetch job posting data.

So, while it’s technically possible, there’s a legal side to it, too. Scraping LinkedIn data may violate their terms of service. That’s especially true if you’re scraping data that’s login-gated. Logging in generally indicates acceptance of LinkedIn’s terms of service (which forbid unauthorized scraping), but the legal consequences of scraping depend on jurisdiction and evolving case law.

You could, however, scrape public data that’s visible without logging in. In this case, you may argue that you haven’t technically accepted their terms of service, and you’re not accessing login-gated data. While it’s a loophole that many seem to utilize, there are still legal risks that depend on factors like jurisdiction, the scraping method, and recent court decisions – some of the data may be considered personal or private.

Tools You’ll Need to Scrape LinkedIn Job Data

To scrape job posting data, you’ll need a few essential tools: Python and libraries. You can use the following Python libraries:

  • requests to make HTTP calls.
  • beautifulsoup4 to parse HTML.
  • selenium to automate browsers and render dynamic content on LinkedIn job pages.

Together, these tools let you scrape LinkedIn job page data and extract details like job titles and descriptions. Selenium can simulate a real browser for pages that load content dynamically, while Requests and BeautifulSoup handle static HTML parsing.

If you’re not into coding or don’t have the experience that comes with building LinkedIn jobs scrapers, there are platforms like Octoparse, Apify, and PhantomBuster that allow you to scrape LinkedIn job postings without writing any code.

They do, however, have limits, and you most likely won’t get the flexibility you would with a custom-built LinkedIn jobs scraper of your own. You may encounter usage caps for the number of job postings you can pull per month or requirements for pricey subscriptions to bump the numbers up.

If you can code and you’re comfortable with it, you may want to go with custom scripts or API-based solutions. Custom scripts give complete control but are more fragile. If LinkedIn suddenly changes its page structure, your scraper is rendered useless.

API-based solutions may provide structured job data, but LinkedIn’s official API doesn’t allow general access to job listings. It’s restricted to approved partners and use cases.

In short, if you want deep access to job data with fewer headaches, APIs might be better. If you need speed or more flexibility at the cost of adjusting your scraper with every update, custom scripts could be better.

Ready to get started?
Register now

Step-by-Step LinkedIn Job Scraping With Python

Below are the steps you need to take to scrape LinkedIn job postings successfully. Keep in mind that some classes might change over time, and you may need to adjust the code.

Step 1: Install Dependencies

You’ll need these Python libraries that you can install using pip:

pip install beautifulsoup4 selenium pandas
  • beautifulsoup4 parses HTML to find the job title, company, location, and other data points.
  • selenium handles JavaScript-rendered content, perfect for dynamic job postings.
  • pandas helps with storing and exporting job postings to files.

Also, download the ChromeDriver or FirefoxDriver that matches your browser version.

Step 2: Load the LinkedIn Jobs Page

Because LinkedIn uses JavaScript to load most job postings, Selenium is usually required. However, advanced users can sometimes capture and replicate LinkedIn’s underlying network/XHR requests instead of using Selenium.

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.get("https://www.linkedin.com/jobs/search/?keywords=python+developer")
time.sleep(5)

It loads the jobs page with search results. You’ll typically see more job postings the more you scroll.

We’ll only be using the above example to check if you get access without any CAPTCHAs. If you do, refer to our CAPTCHA proxies or read our blog for more information.

Step 3: Parse Job Details

Use BeautifulSoup to parse job cards and extract job details like the job title, company name, location, and more.

from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()

try:
    driver.get("https://www.linkedin.com/jobs/search/?keywords=python+developer")

    wait = WebDriverWait(driver, 10)
    wait.until(EC.presence_of_element_located((By.CLASS_NAME, "jobs-search__results-list")))

    time.sleep(3)

    soup = BeautifulSoup(driver.page_source, 'html.parser')

    job_cards = soup.find_all('div', class_='base-search-card')

    jobs = []

    for card in job_cards:
        title_elem = card.find('h3', class_='base-search-card__title')
        title = title_elem.text.strip() if title_elem else None

        company_elem = card.find('h4', class_='base-search-card__subtitle')
        if company_elem:
            company_link = company_elem.find('a')
            company = company_link.text.strip() if company_link else company_elem.text.strip()
        else:
            company = None

        location_elem = card.find('span', class_='job-search-card__location')
        location = location_elem.text.strip() if location_elem else None

        job_link = card.find('a', class_='base-card__full-link')
        job_url = job_link.get('href') if job_link else None

        jobs.append({
            'job_title': title,
            'company': company,
            'location': location,
            'job_url': job_url
        })

    print(f"Found {len(jobs)} jobs:\n")
    for idx, job in enumerate(jobs, 1):
        print(f"{idx}. {job['job_title']}")
        print(f"   Company: {job['company']}")
        print(f"   Location: {job['location']}")
        print(f"   URL: {job['job_url']}")
        print()

finally:
    driver.quit()

It helps you scrape LinkedIn and collect clean job details. Some cards may be missing elements, so check for None before calling .text. Keep in mind that LinkedIn’s job card classes (like jobs-search-results__list-item) often change, so inspect the current page source with your browser’s developer tools and adjust the class selector as needed.

Step 4: Handle Pagination and Scroll

Most LinkedIn job search pages use infinite scrolling to load additional results, though in some cases you may need to click a “See more jobs” button instead.

#Code goes after time.sleep(3)

   last_height = driver.execute_script("return document.body.scrollHeight")
    while True:
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(3) 
        new_height = driver.execute_script("return document.body.scrollHeight")
        
        if new_height == last_height:
            break
        last_height = new_height
#Code ends before soup = BeautifulSoup[...]

Each scroll near the bottom of the page typically triggers new job entries to load into the DOM, though LinkedIn may throttle or stop loading if it detects automation.

We use a basic sleep function to wait before attempting a new scroll. Such an approach is error-prone as it will stop attempting to scroll if loading time takes longer than 3 seconds. You may increase sleep time or use other functions (such as waiting until elements finish loading) to reduce error rates.

After scrolling, re-parse the page using BeautifulSoup to update your list of job postings. At this point, you can scrape LinkedIn job postings in bulk.

Step 5: Export Job Data to CSV or JSON

Use pandas to save your job scraping results:

import pandas as pd

#Code goes after last print()

   df = pd.DataFrame(jobs)
    df.to_csv('linkedin_jobs.csv', index=False)
    df.to_json('linkedin_jobs.json', orient='records', indent=2)
    print(f"Data saved to linkedin_jobs.csv and linkedin_jobs.json")

#Code ends before finally:

Now you should have clean LinkedIn job data to analyze. The CSV or JSON file will include multiple job postings with structured job descriptions, job titles, companies, and locations.

LinkedIn API vs Web Scraping: Which Is Better?

LinkedIn’s APIs can provide structured job posting data, but access is limited to approved partners. Also, there is no publicly available LinkedIn Job Search API.

Even for approved partners, API access is tightly restricted, and general developers cannot retrieve job listings directly from LinkedIn’s API.

Meanwhile, web scraping gives you more data from job postings, like full job descriptions, company names, and other LinkedIn data. But it’s legally risky if not handled right. And even when handled right, you’re still likely to face issues, both technical and legal.

Analyzing and Using the Scraped Job Data

Once you’ve successfully scraped job postings, you can analyze:

  • Top job title trends by city, country, or industry.
  • Common skills required across LinkedIn job listings.
  • Salary ranges, if mentioned in the job descriptions.

Use tools like Pandas, Matplotlib, or even Tableau to make charts. For example, you could map how often the job title “Data Scientist” appears in New York vs San Francisco.

Conclusion

You now know how to scrape LinkedIn job postings using Python. It’s all about using the right tools responsibly and understanding LinkedIn’s terms of service. It’s up to you to choose whether you want to use custom-built LinkedIn jobs scrapers or APIs . One gives more flexibility but is riskier, the other gives you less information but is more stable and compliant.

FAQ

Can you actually scrape LinkedIn jobs?

Yes, you can scrape LinkedIn job listings, but it’s tricky due to security and ethical concerns.

Will LinkedIn ban you for scraping?

Suppose they detect you, yes. LinkedIn monitors traffic and may block your IP or ban accounts used in scraping.

Is scraping traceable or illegal?

It’s traceable and could be illegal depending on how you use it. Always check LinkedIn’s terms of service and local laws about scraping data.

Create Account
Share on
Article by IPRoyal
Meet our writers
Data News in Your Inbox

No spam whatsoever, just pure data gathering news, trending topics and useful links. Unsubscribe anytime.

No spam. Unsubscribe anytime.

Related articles