Skip to main content

LinkedIn automation library - post, fetch, and search via Voyager API

Project description

linkitin

PyPI Python License Tests

Python library for LinkedIn automation via the Voyager API. Fetch posts, search content, and publish — all through an async client.

macOS onlylogin_from_browser() requires macOS and Chrome. The login_with_cookies() path works cross-platform.

Install

pip install linkitin

Requires Python 3.10+.

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Authentication

Chrome proxy mode (recommended — requires macOS and Chrome logged into LinkedIn):

async with LinkitinClient() as client:
    await client.login_from_browser()  # routes API requests through Chrome via AppleScript

Chrome 145+ uses App-Bound Encryption for cookies, making them inaccessible to external tools. login_from_browser() works around this by executing API requests inside Chrome's LinkedIn tab, which automatically includes all session cookies. Requires "Allow JavaScript from Apple Events" enabled in Chrome (View > Developer).

Manual cookie input (if you have raw li_at and JSESSIONID values):

async with LinkitinClient() as client:
    await client.login_with_cookies(li_at="AQED...", jsessionid="ajax:123...")

Cookies from manual input are saved to disk and reused on subsequent runs via login_from_saved().

Usage

import asyncio
from linkitin import LinkitinClient

async def main():
    async with LinkitinClient() as client:
        # Authenticate
        if not await client.login_from_saved():
            await client.login_from_browser()

        # Fetch your posts
        posts = await client.get_my_posts(limit=10)
        for p in posts:
            print(p.text[:80], f"({p.likes} likes)")

        # Search posts
        results = await client.search_posts("AI startups", limit=5)

        # Get home feed
        feed = await client.get_feed(limit=20)

        # Get trending posts
        trending = await client.get_trending_posts(topic="AI", period="past-week", limit=5)

        # Create a text post
        urn = await client.create_post("Hello LinkedIn!", visibility="PUBLIC")

        # Create a post with image
        with open("chart.png", "rb") as f:
            urn = await client.create_post_with_image(
                text="Check out these metrics!",
                image_data=f.read(),
                filename="chart.png",
            )

        # Schedule a post (automatically rounded to next 15-min slot)
        from datetime import datetime, timezone, timedelta
        urn = await client.create_scheduled_post(
            text="Scheduled post — hello future!",
            scheduled_at=datetime.now(timezone.utc) + timedelta(hours=2),
        )

        # Repost a post from the feed
        feed = await client.get_feed(limit=5)
        repost_urn = await client.repost(feed[0].share_urn)

        # Repost with your thoughts
        repost_urn = await client.repost(feed[0].share_urn, text="Great insights!")

asyncio.run(main())

Configuration

LinkitinClient accepts optional parameters to override defaults:

client = LinkitinClient(
    cookies_path="~/.myapp/linkedin_cookies.json",  # default: ~/.linkitin/cookies.json
    timezone="America/New_York",                     # default: detected from system
    timezone_offset=-5.0,                            # default: computed from system
    display_width=1440,                              # default: 1920
    display_height=900,                              # default: 1080
    user_agent="Mozilla/5.0 ...",                    # default: modern Chrome/macOS UA
)

Rate Limiting

All requests go through a token-bucket rate limiter: 10 requests per minute with 1-5 second random jitter between requests. On 429/403 responses, exponential backoff kicks in starting at 30 seconds.

API Reference

Method Description
login_from_browser() Authenticate via Chrome proxy (AppleScript, macOS only)
login_with_cookies(li_at, jsessionid) Authenticate with manual cookies
login_from_saved() Load previously saved cookies
get_my_posts(limit=20) Fetch your posts
search_posts(keywords, limit=20) Search posts by keywords
get_feed(limit=20) Fetch home feed
get_trending_posts(topic, period, limit, from_followed, scrolls) Fetch trending posts sorted by engagement
create_post(text, visibility="PUBLIC") Create a text post
upload_image(image_data, filename) Upload an image, returns media URN
create_post_with_image(text, image_data, filename, visibility="PUBLIC") Create post with image
create_scheduled_post(text, scheduled_at, visibility="PUBLIC") Schedule a text post; scheduled_at rounded to next 15-min slot
create_scheduled_post_with_image(text, image_data, filename, scheduled_at, visibility="PUBLIC") Schedule a post with image; scheduled_at rounded to next 15-min slot
repost(share_urn, text="") Repost (reshare) an existing post
delete_post(post_urn) Delete a post by URN
close() Close the HTTP session

Contributing

See CONTRIBUTING.md for guidelines. PRs welcome!

  • Open issues for bugs or feature requests
  • Keep PRs focused — one change per PR
  • Run python -m pytest tests/ before submitting

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

linkitin-0.1.1.tar.gz (51.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

linkitin-0.1.1-py3-none-any.whl (32.7 kB view details)

Uploaded Python 3

File details

Details for the file linkitin-0.1.1.tar.gz.

File metadata

  • Download URL: linkitin-0.1.1.tar.gz
  • Upload date:
  • Size: 51.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for linkitin-0.1.1.tar.gz
Algorithm Hash digest
SHA256 1a9a3c45aa06fa53259bda53e2c9aed6a224a566eca89aa6d61399099da59874
MD5 a6117510c11f43b78a136a8ceb22dc62
BLAKE2b-256 5d5ac3e31071f84ebb345abb74bff491e9be0f10dc6692ad94da62c4a5061a52

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkitin-0.1.1.tar.gz:

Publisher: publish.yml on ShuhaoZQGG/linkitin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file linkitin-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: linkitin-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 32.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for linkitin-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 392e5b5ca145e233317c74b85e427da798c9621c018d32819e57a273a9ad1218
MD5 69b10fcf6091843c4eb43f6a030b9726
BLAKE2b-256 ad1d135ea9444e5df3e2784cbd0abe4e353b5e75112ecb95fe721dc83610bbc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkitin-0.1.1-py3-none-any.whl:

Publisher: publish.yml on ShuhaoZQGG/linkitin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page