👨‍💼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
A discord bot consuming Notion API to add, retrieve data to Notion databases.

Notion-DiscordBot A discord bot consuming Notion API to add and retrieve data from Notion databases. Instructions to use the bot: Pre-Requisites: a)In

Servatom 57 Dec 29, 2022
Python wrapper for Wikipedia

Wikipedia API Wikipedia-API is easy to use Python wrapper for Wikipedias' API. It supports extracting texts, sections, links, categories, translations

Martin Majlis 369 Dec 30, 2022
A Telegram Bot which will ask new Group Members to verify them by solving an emoji captcha.

Emoji-Captcha-Bot A Telegram Bot which will ask new Group Members to verify them by solving an emoji captcha. About API: Using api.abirhasan.wtf/captc

Abir Hasan 52 Dec 11, 2022
Black-hat with python

black-hat_python Advantages - More advance tool Easy to use allows updating tool update - run bash update.sh Here -: Command to install tool main- clo

Hackers Tech 2 Feb 10, 2022
Lib for create and show QRCode to PIX, you can show this code in another applications for payment by final consumer.

Biblioteca para a geração de codigos QR (BRCode como chamados na documentação do BACEN) a fins de facilitar a exibição para pagamentos ao consumidor.

João Camargo 13 Oct 05, 2022
IMDb + Auto + Unlimited Filter BoT

Telegram Movie Bot Features Auto Filter Manuel Filter IMDB Admin Commands Broadcast Index IMDB search Inline Search Random pics ids and User info Stat

Jos Projects 82 Dec 27, 2022
Nyon-stream - A python script that uses webtorrent to stream nyaa videos directly to mpv

nyon-stream A rather shitty script that uses webtorrent to stream nyaa videos di

18 Feb 08, 2022
Programa de código abierto para probar el API de Bitso, el exchange más importante de América Latina.

Bitso Semiautomático Programa de código abierto para probar el API de Bitso, el exchange más importante de América Latina. Desarrollador Fernando Mire

Fernando Mireles 17 Dec 07, 2022
A mass creator for Discord's new channel threads.

discord-thread-flooder A mass creator for Discord's new channel threads. (obv created by https://github.com/imvast) Warning: this may lag ur pc if u h

Vast 6 Nov 04, 2022
Free python/telegram bot for easy execution and surveillance of crypto trading plans on multiple exchanges.

EazeBot Introduction Have you ever traded cryptocurrencies and lost overview of your planned buys/sells? Have you encountered the experience that your

Marcel Beining 100 Dec 06, 2022
Group Management Bot

❤️ 𝗦𝗛𝗔𝗗𝗜𝗬𝗢 ❤️ A Powerful, Smart And Advance Group Manager ... Written with AioGram , Pyrogram and Telethon... ⭐️ Thanks to everyone who starred

Abdisamad Omar Mohamed 4 Dec 01, 2021
A Bot To Find Telegram User ID Easily

Telegram ID Bot 🤖 A Bot To Find Telegram User ID Easily Made with Python3 (C) @BXBotz Copyright permission under MIT License License - https://githu

MuFaz-TG 6 Nov 21, 2022
A Phyton script working for stream twits from twitter by tweepy to mongoDB

twitter-to-mongo A python script that uses the Tweepy library to pull Tweets with specific keywords from Twitter's Streaming API, and then stores the

3 Feb 03, 2022
A synchronous, object oriented API wrapper for thecatapi

cats.py A synchronous, object oriented API wrapper for thecatapi Table Of Content cats.py Table Of Content Installation Usage Contributing FAQ License

Marcus 2 Feb 04, 2022
Public API client for GETTR, a "non-bias [sic] social network," designed for data archival and analysis.

GoGettr GoGettr is an API client for GETTR, a "non-bias [sic] social network." (We will not reward their domain with a hyperlink.) GoGettr is built an

Stanford Internet Observatory 72 Dec 14, 2022
A badge generator service to count visitors of your markdown file.

Github Visitors Badge A badge generator service to count visitors of your markdown file. Hello every one! In this post, I will tell you the story of m

Kɪꜱᴀʀᴀ Pᴇꜱᴀɴᴊɪᴛʜ Pᴇʀᴇʀᴀ 〄 1 Feb 06, 2022
PancakeTrade - Limit orders and more for PancakeSwap on Binance Smart Chain

PancakeTrade helps you create limit orders and more for your BEP-20 tokens that swap against BNB on PancakeSwap. The bot is controlled by Telegram so you can interact from anywhere.

Valentin Bersier 187 Dec 20, 2022
Data portal client and server for NMDC.

NMDC Server and Client Portal Getting started with Docker install ldc install submodules via git submodule update --init --recursive In order to popul

National Microbiome Data Collaborative 7 Dec 14, 2022
Unarchive Bot for Telegram

Telegram UnArchiver Bot UnArchiveBot: 🇬🇧 Bot that allows you to extract supported archive formats in telegram. 🇹🇷 Desteklenen arşiv biçimleri tele

Hüzünlü Artemis [HuzunluArtemis] 25 May 07, 2022