👨‍💼Linkedin API for Python

Overview

linkedin_api

👨‍💼 Linkedin API for Python

Build Status Documentation Status

No "official" API access required - just use a valid Linkedin account!

Programmatically send messages, get jobs, search profiles and more, all with a regular Linkedin user account!

Before using this project, please consult the Terms and Conditions and Legal Notice.

Installation

⚠️ Python >= 3.6 required

pip3 install linkedin-api~=2.0.0a

Why v2.0.0a?

Example usage

from linkedin_api import Linkedin

# Authenticate using any Linkedin account credentials
api = Linkedin('[email protected]', '*******')

# GET a profile
profile = api.get_profile('billy-g')

# GET a profiles contact info
contact_info = api.get_profile_contact_info('billy-g')

# GET 1st degree connections of a given profile
connections = api.get_profile_connections('1234asc12304')

Documentation

For a complete reference documentation, see the documentation website.

Overview

This project attempts to provide a simple Python interface for the Linkedin API.

Do you mean the legit Linkedin API?

NO! To retrieve structured data, the Linkedin Website uses a service they call Voyager. Voyager endpoints give us access to pretty much everything we could want from Linkedin: profiles, companies, connections, messages, etc. - anything that you can see on linkedin.com, we can get from Voyager.

So specifically, this project aims to provide complete coverage for Voyager.

How do we do it?

How to contribute

Learn how to find endpoints

Development Setup

Dependencies

  • Python 3.7
  • A valid Linkedin user account (don't use your personal account, if possible)
  • pipenv (optional)

Development installation

  1. Create a .env config file. An example is provided in .env.example - you include at least all of the settings set there.

  2. Using pipenv...

    pipenv install --dev
    pipenv shell

Running tests

python -m pytest tests

Troubleshooting

I keep getting a CHALLENGE

Linkedin will throw you a curve ball in the form of a Challenge URL. We currently don't handle this, and so you're kinda screwed. We think it could be only IP-based (i.e. logging in from different location). Your best chance at resolution is to log out and log back in on your browser.

Known reasons for Challenge include:

  • 2FA
  • Rate-limit - "It looks like you’re visiting a very high number of pages on LinkedIn.". Note - n=1 experiment where this page was hit after ~900 contiguous requests in a single session (within the hour) (these included random delays between each request), as well as a bunch of testing, so who knows the actual limit.

Please add more as you come across them.

Search problems

  • Mileage may vary when searching general keywords like "software" using the standard search method. They've recently added some smarts around search whereby they group results by people, company, jobs etc. if the query is general enough. Try to use an entity-specific search method (i.e. search_people) where possible.

In-depth overview

Voyager endpoints look like this:

https://www.linkedin.com/voyager/api/identity/profileView/tom-quirk

Or, more clearly

 ___________________________________ _______________________________
|             base path             |            resource           |
https://www.linkedin.com/voyager/api /identity/profileView/tom-quirk

They are authenticated with a simple cookie, which we send with every request, along with a bunch of headers.

To get a cookie, we POST a given username and password (of a valid Linkedin user account) to https://www.linkedin.com/uas/authenticate.

To find endpoints

We're looking at the Linkedin website and we spot some data we want. What now?

The most reliable method to find the relevant endpoint is to:

  1. view source

  2. command-f/search the page for some keyword in the data. This will exist inside of a <code> tag.

  3. Scroll down to the next adjacent element which will be another <code> tag, probably with an id that looks something like

    <code style="display: none" id="datalet-bpr-guid-3900675">
      {"request":"/voyager/api/identity/profiles/tom-quirk/profileView","status":200,"body":"bpr-guid-3900675"}
    </code>
  4. The value of request is the url! 🤘

You can also use the network tab in you browsers developer tools, but you will encounter mixed results.

How Clients query Voyager

Linkedin seems to have developed an internal query language/syntax where Clients (i.e. front-ends like linkedin.com) to specify what data they want (similar to the GraphQL concept). If anyone knows what this is, I'd love to know!.

Here's an example of making a request for an organisation's name and groups (the Linkedin groups it manages):

/voyager/api/organization/companies?decoration=(name,groups*~(entityUrn,largeLogo,groupName,memberCount,websiteUrl,url))&q=universalName&universalName=linkedin

The "querying" happens in the decoration parameter, which looks like

(
    name,
    groups*~(entityUrn,largeLogo,groupName,memberCount,websiteUrl,url)
)

So here, we request an organisation name, and a list of groups, where for each group we want largeLogo, groupName, etc.

Different endpoints use different parameters (and perhaps even different syntaxes) to specify these queries. Notice that the above query had a parameter q whose value was universalName; the query was then specified with the decoration parameter.

In contrast, the /search/cluster endpoint uses q=guided, and specifies its query with the guided parameter, whose value is something like

List(v->PEOPLE)

It could be possible to document (and implement a nice interface for) this query language - as we add more endpoints to this project, I'm sure it will become more clear if such a thing would be possible (and if it's worth it).

Terms and Conditions

By using this project, you agree to the following Terms and Conditions. We reserve the right to block any user of this repository that does not meet these conditions.

Usage

This project may not be used for any of the following:

  • Commercial use
  • Spam
  • Storage of any Personally Identifiable Information
  • Personal abuse (i.e. verbal abuse)

Legal

This code is in no way affiliated with, authorized, maintained, sponsored or endorsed by Linkedin or any of its affiliates or subsidiaries. This is an independent and unofficial API. Use at your own risk.

This project violates Linkedin's User Agreement Section 8.2, and because of this, Linkedin may (and will) temporarily or permanently ban your account. We are not responsible for your account being banned.

Versioning Note

Tl;dr: Don't use anything < v2.0.0a.

Releases/tags for this package have not been kept up to date with changes and thus versions (like v1.0.0) are misleading and do not represent "stability". Eventually, v2.0.0 will be the "stable" release.

Comments
  • Support ability to send Linkedin connection requests

    Support ability to send Linkedin connection requests

    I.e. Add people on Linkedin

    POST

    {"trackingId":"XVpxyROJQ1ybTCQtEFrl8A==","invitations":[],"excludeInvitations":[],"invitee":{"com.linkedin.voyager.growth.invitation.InviteeProfile":{"profileId":"<profile_id>"}}}
    

    to url

    /voyager/api/growth/normInvitations
    
    enhancement linkedin API endpoint 
    opened by tomquirk 19
  • Added add_connection functionality

    Added add_connection functionality

    Fixes #10, #133

    • Added a function to generate a random TrackingId
    • Added add_connection functionality

    Do let me know how I could fix the tests as well.

    opened by abinpaul1 16
  • search_people with regions fails

    search_people with regions fails

    I run the code listed in the examples (and other attempts)

    results = linkedin.search_people( keywords='software,lol', connection_of='AC000120303', network_depth='F', regions=[4909], industries=[29, 1] )

    but I got this error


    in search_people filters.append(f'geoRegion->{"|".join(regions)}') TypeError: sequence item 0: expected str instance, int found


    bug 
    opened by Ulixestoitaca 15
  • get all posts from profile

    get all posts from profile

    Hi guys,

    Hope you are all well !

    I was wondering if I can fetch the list of all posts (for eg, https://www.linkedin.com/in/philipvollet/detail/recent-activity/shares) with linkedin-api ?

    Thanks for your inputs and insights on that.

    Cheers, X

    linkedin API endpoint 
    opened by paper2code-bot 12
  • `search_jobs` doesn't work

    `search_jobs` doesn't work

    I got this error:

    jobs = api.search_jobs(keywords='software engineer',experience='2',job_type='F')
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-7-e8676eef6663> in <module>()
    ----> 1 jobs = api.search_jobs(keywords='software engineer',experience='2',job_type='F')
    
    TypeError: search_jobs() got an unexpected keyword argument 'experience'
    

    I installed with

    pip3 install linkedin-api~=2.0.0a
    
    opened by khangly 11
  • search_people or search always returns same first result that found something

    search_people or search always returns same first result that found something

    When calling search_people or search multiple times, as soon as there is a result these methods will keep returning that same result for all subsequent searches.

    bug 
    opened by woutwoot 11
  • Add support for creating a new conversation

    Add support for creating a new conversation

    I can't send param's to this function. I notice that you put a comment line that

    # passing 'params' doesn't work properly, think it's to do with List(). 
    # Might be a bug in 'requests' ? 
    

    Is there any quick fix for this? I really need this.

    linkedin API endpoint needs investigation 
    opened by cyb3rsalih 9
  • Improve authentication

    Improve authentication "anti-bot-detection" mechanism

    Not sure if you've encountered this case, but the authentication sometimes doesn't work for me. The following exception will be thrown out:

    res.status_code 401
    Traceback (most recent call last):
      File "F:/linkedin-api/examples/basic.py", line 60, in <module>
        linkedin = Linkedin(credentials['username'], credentials['password'])
      File "F:\linkedin-api\linkedin_api\linkedin.py", line 30, in __init__
        self.client.authenticate(username, password)
      File "F:\linkedin-api\linkedin_api\client.py", line 102, in authenticate
        raise Exception()
    Exception
    

    I am thinking it might be the case that LinkedIn is blocking the API for some reason, but the account itself is fine (I can still login thru the web portal) - so I am wondering if you've encountered this before?

    enhancement 
    opened by xiaoyongzhu 9
  • linkedin_api.client.ChallengeException: CHALLENGE

    linkedin_api.client.ChallengeException: CHALLENGE

    As mentioned in Readme. Challenge error is coming because of continuous requests. But it is not true in my case. CHALLENGE error is coming after 1st request. After some analysis, I found out that this is happening after executing self.client.authenticate(username, password) function in linkdedin.py file. After executing this script one-time LinkedIn in sending me following mail:

    Hi XYZ,   To make sure you continue having the best experience possible on LinkedIn, we're regularly monitoring our site and the Internet to keep your account information safe. We've recently noticed a potential risk to your LinkedIn account coming from outside LinkedIn and just to be safe, we've locked your account for now. You'll need to reset your password in order to unlock your account. Here's how: Go to the LinkedIn website. Next to the password field, click the "Forgot your password" link, and enter your email address. You'll get an email from LinkedIn asking you to click a link that will help you reset your password. Once you've reset your password, a confirmation email will be sent to the confirmed email addresses on your account.

    opened by Vikku14 8
  • AttributeError: 'Linkedin' object has no attribute 'add_connection'

    AttributeError: 'Linkedin' object has no attribute 'add_connection'

    I'm using latest version of linkedin-api yet I'm getting this error:

    ERROR:

    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-5-68dfe11587c3> in <module>
          1 # for user in search_ppl:
    ----> 2 api.add_connection(profile_public_id='user-profile-here', message='some message here')
    
    AttributeError: 'Linkedin' object has no attribute 'add_connection'
    

    After running pip show linkedin-api

    Name: linkedin-api
    Version: 2.0.0a5
    Summary: Python wrapper for the Linkedin API
    Home-page: https://github.com/tomquirk/linkedin-api
    Author: Tom Quirk
    Author-email: [email protected]
    License: MIT
    Location: c:\users\hamza\appdata\local\programs\python\python39\lib\site-packages
    Requires: beautifulsoup4, requests, lxml
    Required-by: 
    

    CODE:

    api.add_connection(profile_public_id='user-profile-here', message='some message here')
    
    opened by mhmzdev 7
  • Linkedin function not working

    Linkedin function not working

    Hi tomquirk,

    Thank you for your great package! However, as a newbie, I met several problems since the install step.

    • It seems -e should be removed from the Installation step.

    • And after I load the package, I can't even use the first step by Linkedin function. For example, this is not working api = Linkedin('[email protected]', 'iheartmicrosoft'). And the error is 'CookieRepository' object has no attribute 'logger'.

    I would be appreciated if you could tell me how to solve this problem. And my system is Windows 10 pro, Python 3.7.3 with Anaconda. Thanks for your reply!

    Sheng

    bug 
    opened by marc233 7
  • JSON decode error, no data on getting profile

    JSON decode error, no data on getting profile

    The package worked for me a few weeks ago but is now no longer working for some reason.

    Here's my simple code:

    from linkedin_api import Linkedin
    
    api: Unknown  = Linkedin('***', '***')
    
    # GET a profile
    profile: Unknown  = api.get_profile('billy-g')
    print(profile)
    

    When using the https://github.com/tomquirk/linkedin-api.git version of the package, this fails with

    Traceback (most recent call last):
      File "/Users/hima/Workspace/del/.venv/lib/python3.10/site-packages/requests/models.py", line 971, in json
        return complexjson.loads(self.text, **kwargs)
      File "/Users/hima/.pyenv/versions/3.10.4/lib/python3.10/json/__init__.py", line 346, in loads
        return _default_decoder.decode(s)
      File "/Users/hima/.pyenv/versions/3.10.4/lib/python3.10/json/decoder.py", line 337, in decode
        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
      File "/Users/hima/.pyenv/versions/3.10.4/lib/python3.10/json/decoder.py", line 355, in raw_decode
        raise JSONDecodeError("Expecting value", s, err.value) from None
    json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/Users/hima/Workspace/del/run.py", line 6, in <module>
        profile = api.get_profile('billy-g')
      File "/Users/hima/Workspace/del/.venv/lib/python3.10/site-packages/linkedin_api/linkedin.py", line 622, in get_prof
    ile
        data = res.json()
      File "/Users/hima/Workspace/del/.venv/lib/python3.10/site-packages/requests/models.py", line 975, in json
        raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
    requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    
    

    When using the 2.0.0a version of the package, it fails during authentication instead with

    Traceback (most recent call last):
      File "/Users/hima/Workspace/del/run.py", line 3, in <module>
        api = Linkedin('***', '***')
      File "/Users/hima/Workspace/del/.venv/lib/python3.10/site-packages/linkedin_api/linkedin.py", line 69, in __init__
        self.client.authenticate(username, password)
      File "/Users/hima/Workspace/del/.venv/lib/python3.10/site-packages/linkedin_api/client.py", line 99, in authenticat
    e
        self._fetch_metadata()
      File "/Users/hima/Workspace/del/.venv/lib/python3.10/site-packages/linkedin_api/client.py", line 122, in _fetch_met
    adata
        ).attrs["content"]
    AttributeError: 'NoneType' object has no attribute 'attrs'
    

    I'm on python 3.10.4

    Any ideas why?

    opened by himat 1
  • Version 2.0.0 requires lxml that cannot be installed in mac m2

    Version 2.0.0 requires lxml that cannot be installed in mac m2

    Hello, i tried to install version 2, however, due to problems with lxml installation i cannot manage to install the lastest version, only the unmaintained 1.0.0. Anyone can help?

    opened by manuelrech 0
  • Search Companies Filters

    Search Companies Filters

    Has anyone successfully managed to add filters to the search companies such as location, industry and company size??

    I have tried to play with the code but to no success currently

    opened by SIF-FCHIARI 2
  • How to get saved posts?

    How to get saved posts?

    Hi, I would like to retrieve my saved posts. The URL is https://www.linkedin.com/my-items/saved-posts

    I believed I found the query using the Chrome Devtools but it doesn't work. I get an HTTP 400 error ("Bad request")

    Do you think it's possible to retrieve the saved posts?


    Here the code I use:

    api = Linkedin('<login>', '<password>')
    params = {
            "decorationId": "com.linkedin.voyager.dash.deco.search.SearchClusterCollection-169",
            "q": "all",
            "query":  "(flagshipSearchIntent:SEARCH_MY_ITEMS_SAVED_POSTS)",
            "start": 0
        }
    api._fetch(f"/search/dash/clusters", params=params)  # get a 400 error here
    
    opened by apallier 0
  • Add method to get social reactions for a post.

    Add method to get social reactions for a post.

    This shows likes, etc. for a post.

    In [2]: from linkedin_api import Linkedin
    
    In [3]: api = Linkedin(USERNAME, PASSWORD)
    
    In [4]: reactions = api.get_social_reactions("urn:li:activity:6975230311307644928", max_results=10)
    
    In [5]: reactions[0]
    {'actor': {'profileUrn': {'entityUrn': 'urn:li:fsd_profile:ACoAABO7kRoBn-gddYTjVljt4Ox54a6jjuE-5pc',
    ...
    
    opened by kjoconnor 0
Releases(2.0.0-alpha.4)
Owner
Tom Quirk
Tom Quirk
Solcast rooftop api for HA

Solcast Solar Home Assistant(https://www.home-assistant.io/) Component This custom component integrates the Solcast API into Home Assistant. Modified

Greg 1 Oct 11, 2021
The Easy-to-use Dialogue Response Selection Toolkit for Researchers

Easy-to-use toolkit for retrieval-based Chatbot Our released data can be found at this link. Make sure the following steps are adopted to use our code

GMFTBY 32 Nov 13, 2022
Rotten Tomatoes API for Python

rottentomatoes.py rottentomatoes offers an easy-to-use Python wrapper to interact with the Rotten Tomatoes API. Before you try and use the API, make s

Zach Williams 88 Dec 15, 2022
Python SDK for LUSID by FINBOURNE, a bi-temporal investment management data platform with portfolio accounting capabilities.

LUSID® Python SDK This is the Python SDK for LUSID by FINBOURNE, a bi-temporal investment management data platform with portfolio accounting capabilit

FINBOURNE 6 Dec 24, 2022
Python Dialogflow CX Scripting API (SCRAPI)

Python Dialogflow CX Scripting API (SCRAPI) A high level scripting API for bot builders, developers, and maintainers. Table of Contents Introduction W

Google Cloud Platform 39 Dec 09, 2022
The Simple Google Colab Notebook to Download Files from Direct Link to Google Drive with custom name and bulk link support.

Direct Link to Google Drive (Advanced! 🔥 ) The Most Advanced yet Simple Google Colab Notebook to Download Files from Direct Link to Google Drive. 🆕

Dr.Caduceus 14 Jul 26, 2022
A Bot to Track Kernel Upstreams from kernel.org and Post it on Telegram Channel

Channel Kernel Tracker is the channel where the bot will be sending the updates in. Introduction This is a Telegram Bot to Track Kernel Upstreams kern

Kartikeya Hegde 3 Oct 05, 2021
Python wrapper for the Sportradar APIs ⚽️🏈

Sportradar APIs This is a Python wrapper for the sports APIs provided by Sportradar. You'll need to sign up for an API key to use the service. Sportra

John W. Miller 39 Jan 01, 2023
How to add reaction on message discord.py

BA / HR / RS: Python (discord.py) skripta pomocu koje dodajete reakciju na vasu poruku putem komande !v ili da se dodaje samo u nekoj odredjenoj sobi.

Seekii 3 Dec 23, 2021
Bot Telegram per creare e gestire un Babbo Natale Segreto con amici ecc

Babbo Natale Segreto: Telegram Bot Bot Telegram per creare e gestire un Babbo Natale Segreto con amici ecc. Che cos'è? Il Babbo Natale Segreto è un gi

Francesco Ciociola 2 Jul 18, 2022
A python script for hitting the kik API to enumerate people based on a username/userlist

kick3d Recon script for enumerating users off of the Kik API. This script has the ability to check single usernames or run through a userlist of usern

Sakura Samurai 19 Oct 04, 2021
Simple spam bot made in python

Simple Spam Bot A Simple and easy way to be the most hated person between your friends, All you have to do is spam the group chat using this bot until

Kareem Osama 6 Sep 05, 2022
API which returns cusswords , can be used to check cusswords in bots etc.

Anti-abuse-api-flask API which returns cusswords , can be used to check cusswords in bots etc. Run pip install -r requirements.txt py app.py API Endpo

8 Jan 03, 2023
NitroSniper - A discord nitro sniper, it uses 2 account tokens here's the explanation

Discord-Nitro-Sniper This is a discord nitro sniper, it uses 2 account tokens he

vanis / 1800 0 Jan 20, 2022
Discord heximals: More colors for your bot

DISCORD-HEXIMALS More colors for your bot ! Support : okimii#0434 COLORS ( 742 )

4 Feb 04, 2022
Prime Mega is a modular bot running on python3 with autobots theme and have a lot features.

PRIME MEGA Prime Mega is a modular bot running on python3 with autobots theme and have a lot features. Easiest Way To Deploy On Heroku This Bot is Cre

『TØNIC』 乂 ₭ILLΣR 45 Dec 15, 2022
Trading Strategies (~50%) developed by GreenT on QuantConnect platform over the autumn quarter

Trading Strategies ~50% of codes from the Applied Financial Technology Course. Contributors: Claire W. Derrick T. Frank L. Utkarsh T. Course Leads: Dy

Utkarsh 2 Feb 07, 2022
An api, written in Python, for Investopedia's paper trading stock simulator.

investopedia-trading-api An API, written in Python, for Investopedia's paper trading stock simulator. Pull requests welcome. This library is now Pytho

Kirk Thaker 178 Jan 06, 2023
Google translator bot using pyTelegramBotAPI

iTranslator-bot Super google translator bot using pyTelegramBotAPI A bot is a professional bot that automatically detects a language in texts or capti

Abdulatif 6 Nov 22, 2022
SpotPlay2YouPlay - Converts new additions to a Spotify playlist to a matching Youtube playlist

SpotPlay2YouPlay - Converts new additions to a Spotify playlist to a matching Youtube playlist, can also be configured to converting whole playlists with the refresh fun

9 Mar 06, 2022