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

GoViral Integration

GoViral uses linkitin as a LinkedIn fallback when official API credentials are unavailable.

Bridge script: scripts/linkitin_bridge.py reads JSON commands from stdin and writes JSON responses to stdout, allowing Go to drive linkitin via subprocess.

Setup from GoViral:

goviral linkitin-login    # extracts LinkedIn cookies from Chrome

This saves cookies to ~/.goviral/linkitin_cookies.json (GoViral's own path, passed explicitly).

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.0.tar.gz (51.4 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.0-py3-none-any.whl (33.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: linkitin-0.1.0.tar.gz
  • Upload date:
  • Size: 51.4 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.0.tar.gz
Algorithm Hash digest
SHA256 21080934a20b3efee02ade96fab06940e0e6291752f0d7f68857b4de9bb56b5e
MD5 d6c4e43342e987766834f837fcd7290f
BLAKE2b-256 7cefaf6e954d44ed4642d3b85a8b8d2400f31a15c276d563991745b29fcedee9

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: linkitin-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 33.0 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 271ae71672406ebb8ae27d365f45148bd433195467e01687e1d4bceaac98aa08
MD5 60dff9d7a4f787a52e1f3768b410aac7
BLAKE2b-256 ce543d504b10df47f8b19991fbc0a7c195681b9d203c7c05029c161d15c326b0

See more details on using hashes here.

Provenance

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