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),
        )

        # Comment on a post
        feed = await client.get_feed(limit=5)
        comment_urn = await client.comment_post(feed[0].urn, "Great post!")

        # Reply to a comment (threaded)
        reply_urn = await client.comment_post(
            feed[0].urn, "Thanks!", parent_comment_urn=comment_urn
        )

        # Repost a post from the feed
        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
comment_post(post_urn, text, parent_comment_urn="") Comment on a post (or reply to a comment)
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.2.tar.gz (56.5 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.2-py3-none-any.whl (34.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: linkitin-0.1.2.tar.gz
  • Upload date:
  • Size: 56.5 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.2.tar.gz
Algorithm Hash digest
SHA256 784608db0da7a5542e551caf18237cd0de955930a3a6b928cfc6eaeabc11519d
MD5 3e95a7ef156adcfbcac291229d08692f
BLAKE2b-256 334093fd871caf1ed52ba6e0e47b1e5beba0978aec8ac6e358317c2ead21c7e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkitin-0.1.2.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.2-py3-none-any.whl.

File metadata

  • Download URL: linkitin-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 34.1 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 541d38e8830cb1fe1c2bc651bf106b4a82c4c703b65fcbc02ce79e1a4294fffc
MD5 3d79f603870153a4ff4a1f141060aab5
BLAKE2b-256 04870699231351c1a085d476cf3b2be7f2337865092acf69a87e0298bc446635

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkitin-0.1.2-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