3 min read

LinkedIn Automation (Official API)

This guide demonstrates how to automate posting to LinkedIn using the official LinkedIn API. It uses requests to interact with the REST API endpoints for retrieving user details and creating posts.

Modules Used:

Prerequisites

  1. LinkedIn Developer App: Go to LinkedIn Developers, create an app.
  2. Permissions: Under "Products", request access to Share on LinkedIn (w_member_social) and Sign In with LinkedIn (r_liteprofile or r_emailaddress).
  3. Access Token:
    • Go to the Auth tab of your app.
    • Use the OAuth 2.0 tools link (Token Generator) to generate an access token for your personal account.
    • Select the scopes (w_member_social, r_liteprofile).
    • Copy the Access Token.

Installation

pip install requests python-dotenv

Setup

Create a .env file in your project directory:

LINKEDIN_ACCESS_TOKEN=your_long_access_token_here

The Code

Save this as linkedin_bot.py.

import requests
import os
import argparse
import sys
import json
from dotenv import load_dotenv

# Load Config
load_dotenv()
ACCESS_TOKEN = os.getenv("LINKEDIN_ACCESS_TOKEN")

API_URL = "https://api.linkedin.com/v2"

def get_headers():
    if not ACCESS_TOKEN:
        print("Error: LINKEDIN_ACCESS_TOKEN not found in .env")
        sys.exit(1)
    return {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "Content-Type": "application/json",
        "X-Restli-Protocol-Version": "2.0.0"
    }

def get_user_urn():
    """Fetches the authenticated user's URN (ID)."""
    url = f"{API_URL}/me"
    response = requests.get(url, headers=get_headers())

    if response.status_code == 200:
        data = response.json()
        # URN format: urn:li:person:ID
        return f"urn:li:person:{data['id']}"
    else:
        print(f"Error fetching profile: {response.status_code} - {response.text}")
        sys.exit(1)

def post_text_share(urn, text, visibility="PUBLIC"):
    """Posts a text update to LinkedIn."""
    url = f"{API_URL}/ugcPosts"

    # Visibility mapping
    share_visibility = "PUBLIC" if visibility.upper() == "PUBLIC" else "CONNECTIONS"

    payload = {
        "author": urn,
        "lifecycleState": "PUBLISHED",
        "specificContent": {
            "com.linkedin.ugc.ShareContent": {
                "shareCommentary": {
                    "text": text
                },
                "shareMediaCategory": "NONE"
            }
        },
        "visibility": {
            "com.linkedin.ugc.MemberNetworkVisibility": share_visibility
        }
    }

    print(f"Posting to LinkedIn as {urn}...")
    response = requests.post(url, headers=get_headers(), data=json.dumps(payload))

    if response.status_code == 201:
        print("Success! Post created.")
        print(f"Post ID: {response.json()['id']}")
    else:
        print(f"Error posting: {response.status_code} - {response.text}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="LinkedIn Automation Bot")
    parser.add_argument("text", help="Text content to post")
    parser.add_argument("--visibility", default="PUBLIC", choices=["PUBLIC", "CONNECTIONS"], help="Post visibility")

    args = parser.parse_args()

    # 1. Get User ID (URN)
    user_urn = get_user_urn()

    # 2. Post
    post_text_share(user_urn, args.text, args.visibility)

Usage

python linkedin_bot.py "Hello LinkedIn network! This post was automated with Python."

programming/python/python