LinkedIn Gateway API
Unofficial LinkedIn API Gateway - Access LinkedIn data programmatically through a Chrome extension and REST API. Open-core solution for self-hosting.
β οΈ Important Notice
This is an unofficial tool and is not affiliated with, endorsed by, or connected to LinkedIn Corporation. Use at your own risk and in accordance with LinkedIn's Terms of Service.
π― Overview
LinkedIn Gateway bridges the gap between LinkedIn's web interface and your applications by providing:
- Chrome Extension: Captures LinkedIn session and proxies requests
- REST API: Clean, documented endpoints for LinkedIn data
- Self-Hosted: Full control over your data and infrastructure
- Open Core: Free and open source for self-hosting
Dual Execution Architecture
The system supports two modes of operation:
- Browser Proxy Mode (Default): Routes requests through the Chrome extension using your active LinkedIn session
- Server-Side Execution: Direct API calls from the backend using stored session cookies (requires self-hosted deployment)
β Key Features
Complete LinkedIn API Coverage
- β’ Feed operations (fetch posts with engagement data)
- β’ Connection management (send/accept requests)
- β’ Messaging (send direct messages)
- β’ Profile scraping (extract profile data)
- β’ Comment operations (post & reply)
- β’ Reactions scraping (fetch post likes with user details)
- β’ User comments history (fetch all comments made by a profile)
Dual Execution Modes
- β’ Server-side execution for automated workflows
- β’ Browser proxy mode for enhanced session reliability
- β’ Seamless switching between modes
- β’ Automatic fallback handling
Enterprise-Ready
- β’ API key authentication with rate limiting
- β’ PostgreSQL database for data persistence
- β’ WebSocket support for real-time operations
- β’ Comprehensive error handling and logging
Production Deployment
- β’ Docker Compose setup included
- β’ Automated database migrations
- β’ Health checks and monitoring
- β’ HTTPS support with OAuth integration
ποΈ Architecture
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Your App β β LinkedIn β β Chrome β
β (API Client) ββββββββββΆβ Gateway API βββββββββββ Extension β
β β REST β (FastAPI) β WSS β (Proxy) β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β β
β β
βΌ βΌ
ββββββββββββββββββββ βββββββββββββββββββ
β PostgreSQL β β LinkedIn β
β Database β β Internal API β
ββββββββββββββββββββ βββββββββββββββββββ
Execution Modes
1. Server-Side Execution (server_call=true)
The backend directly calls LinkedIn's internal APIs using stored session cookies.
β Pros:
- β’ Fully automated, no browser required
- β’ Faster response times
- β’ Suitable for batch operations
β οΈ Cons:
- β’ Requires valid LinkedIn session cookies
- β’ May need periodic session refresh
2. Browser Proxy Mode (server_call=false)
Requests are proxied through the Chrome extension, which uses the user's active LinkedIn session.
β Pros:
- β’ Always uses fresh, valid session
- β’ More reliable for long-running operations
- β’ Automatic session management
β οΈ Cons:
- β’ Requires Chrome extension to be running
- β’ Slightly higher latency
π Quick Start
Prerequisites
- Docker & Docker Compose (required - must be installed before running the installer)
- OR Python 3.11+ and PostgreSQL (for manual setup without Docker)
- Google Chrome or Chromium-based browser
- LinkedIn Account (required for functionality)
Option 1: Docker Deployment (Recommended)
# Clone the repository
git clone https://github.com/vcentea/linkedin-gateway.git
cd linkedin-gateway
# Run the installation script
# Windows
deployment\scripts\install-core.bat
# Linux/Mac
chmod +x deployment/scripts/install-core.sh
./deployment/scripts/install-core.sh
# Access the API
# API: http://localhost:7778
# API Docs: http://localhost:7778/docs
# Health Check: http://localhost:7778/health
π Installing Docker
- β’ Linux: Ubuntu/Debian or CentOS/RHEL
- β’ Windows/macOS: Docker Desktop
Option 2: Local Development
# 1. Set up virtual environment
python -m venv venv
source venv/bin/activate # Linux/Mac
# or
venv\Scripts\activate # Windows
# 2. Install dependencies
cd backend
pip install -r requirements/base.txt
# 3. Configure environment
cp .env.example .env
# Edit .env with your database credentials
# 4. Run database migrations
alembic upgrade head
# 5. Start the server
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Chrome Extension Setup
cd chrome-extension
# Install dependencies
npm install
# Build for development
npm run build:dev
# Build for production
npm run build:prod
Load in Chrome:
- Go to
chrome://extensions/ - Enable "Developer mode"
- Click "Load unpacked"
- Select
chrome-extension/dist-dev/(ordist-prod/)
π Authentication
LinkedIn Gateway uses API keys for authentication. Generate your API key through the web interface or OAuth flow.
API Key Authentication
All API endpoints require authentication using an API key. You can provide the key in two ways:
1. Header Authentication (Recommended)
Pass the API key in the X-API-Key header:
curl -X POST https://localhost:7778/api/v1/feed/posts \
-H "X-API-Key: LKG_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"start_index": 0, "count": 10, "server_call": false}'
2. Body Authentication
Include the API key in the request body:
{
"api_key": "LKG_your_api_key_here",
"start_index": 0,
"count": 10,
"server_call": false
}
π‘ server_call Parameter
All endpoints support dual execution modes via the server_call parameter:
- β’
server_call: false(default) - Executes via browser extension proxy (requires extension installed and connected) - β’
server_call: true- Executes directly from server using stored LinkedIn session (requires self-hosted deployment with valid session)
OAuth 2.0 Flow
LinkedIn Gateway supports LinkedIn OAuth for user authentication:
- User initiates login via Chrome extension
- Extension redirects to LinkedIn OAuth
- LinkedIn redirects back with authorization code
- Backend exchanges code for access token
- User session is created with JWT token
- API key is generated for programmatic access
π API Key Management
- β’ Format:
LKG_prefix_secret - β’ Storage: Hashed in PostgreSQL database
- β’ Scope: Per-user, with rate limiting
- β’ Rotation: Users can regenerate keys anytime
π API Reference
All endpoints support dual execution modes via the server_call parameter.
Base URL: http://localhost:7778 (or your deployed server URL)
Feed Operations
POST
/api/v1/feed/posts
Fetch posts from your LinkedIn feed with full engagement data.
Headers:
X-API-Key: LKG_your_api_key_here
Content-Type: application/json
Request Body:
{
"start_index": 0,
"count": 10,
"server_call": false
}
Parameters:
| Parameter | Type | Description |
|---|---|---|
start_index |
integer | Starting index for posts (default: 0) |
count |
integer | Number of posts to fetch (1-50, default: 10) |
server_call |
boolean | Execution mode (false: proxy, true: server) |
Response:
[
{
"id": 1,
"postid": "urn:li:activity:7123456789",
"ugcpostid": "urn:li:ugcPost:7123456789",
"url": "https://linkedin.com/feed/update/urn:li:activity:7123456789",
"postcontent": "Post content here...",
"author_id": 42,
"author_linkedin_id": "john-doe-123",
"author_name": "John Doe",
"author_headline": "Software Engineer at TechCorp",
"author_connection_degree": "1st",
"reactions": 42,
"comments": 5,
"reposts": 3,
"engagement": 50,
"timestamp": "2025-01-15T10:30:00Z"
}
]
Connection Management
POST
/api/v1/connections/simple
Send a simple connection request without a message.
Request Body:
{
"profile_identifier": "john-doe-123",
"server_call": false
}
Parameters:
- β’
profile_identifier(string) - LinkedIn profile ID (e.g., 'john-doe-123') or full profile URL - β’
server_call(boolean) - Execution mode (false: proxy, true: server)
Response:
{
"success": true
}
POST
/api/v1/connections/with-message
Send a connection request with a personalized message.
Request Body:
{
"profile_identifier": "john-doe-123",
"message": "Hi John, I'd like to connect!",
"server_call": false
}
Parameters:
- β’
profile_identifier(string) - LinkedIn profile ID or full profile URL - β’
message(string) - Custom message to include with connection request - β’
server_call(boolean) - Execution mode (false: proxy, true: server)
Response:
{
"success": true
}
Messaging
POST
/api/v1/messages/send
Send a direct message to a LinkedIn profile.
Request Body:
{
"profile_identifier": "john-doe-123",
"message_text": "Hello! I saw your profile...",
"server_call": false
}
Parameters:
- β’
profile_identifier(string) - LinkedIn profile ID or full profile URL - β’
message_text(string) - Message text to send - β’
server_call(boolean) - Execution mode (false: proxy, true: server)
Response:
{
"success": true
}
POST
/api/v1/messages/my-id
Get your authenticated user's LinkedIn profile ID.
Request Body:
{
"server_call": false
}
Response:
{
"success": true,
"profile_id": "john-doe-123"
}
Profile Operations
POST
/api/v1/profiles/scrape
Extract complete profile data including identity, contact info, about section, and skills.
Request Body:
{
"profile_id": "john-doe-123",
"server_call": false
}
Parameters:
- β’
profile_id(string) - LinkedIn profile ID or full profile URL - β’
server_call(boolean) - Execution mode (false: proxy, true: server)
POST
/api/v1/profiles/experiences
Scrape work experience history from a LinkedIn profile.
Request Body:
{
"profile_id": "john-doe-123",
"server_call": false
}
POST
/api/v1/profiles/identity
Get identity data (name, headline, location, connection degree, follower count).
Request Body:
{
"profile_id": "john-doe-123",
"server_call": false
}
POST
/api/v1/posts/profile-posts
Fetch posts published by a specific LinkedIn profile.
Request Body:
{
"profile_id": "john-doe-123",
"count": 10,
"server_call": false
}
Parameters:
- β’
profile_id(string) - LinkedIn profile ID or URL - β’
count(integer) - Number of posts to fetch (default: 10) - β’
server_call(boolean) - Execution mode
Reactions
POST
/api/v1/posts/get-reactions
Fetch all reactions (likes) for a LinkedIn post with detailed reactor information.
Headers:
X-API-Key: LKG_your_api_key_here
Content-Type: application/json
Request Body:
{
"post_url": "https://linkedin.com/feed/update/urn:li:activity:7123456789",
"count": -1,
"server_call": false,
"min_delay": 0.5,
"max_delay": 1.5
}
Parameters:
| Parameter | Type | Description |
|---|---|---|
post_url |
string | LinkedIn post URL or activity URN |
count |
integer | Number of reactions to fetch (-1 for all, default: 10) |
server_call |
boolean | Execution mode (false: proxy, true: server) |
min_delay |
float | Min delay between pagination requests (seconds, default: 0.5) |
max_delay |
float | Max delay between pagination requests (seconds, default: 1.5) |
Response:
{
"data": [
{
"userId": "ACoAAD7-6OkBzHtPyDUD0wH2GSITJntEoxFm8K0",
"userName": "John Doe",
"userTitle": "Software Engineer at TechCorp",
"connectionLevel": "1st",
"reactionType": "LIKE"
},
{
"userId": "ACoAACXyz123...",
"userName": "Jane Smith",
"userTitle": "Product Manager",
"connectionLevel": "2nd",
"reactionType": "PRAISE"
}
]
}
π‘ Reaction Types
LinkedIn supports multiple reaction types:
- β’ LIKE - Standard like reaction
- β’ PRAISE - Celebrate/hands clapping
- β’ APPRECIATION - Love/heart
- β’ EMPATHY - Care/hug
- β’ INTEREST - Curious/lightbulb
- β’ ENTERTAINMENT - Funny/laughing
User Comments
POST
/api/v1/profile/comments
Fetch all comments made by a specific user profile with full context including posts and parent comments.
Headers:
X-API-Key: LKG_your_api_key_here
Content-Type: application/json
Request Body:
{
"profile_id": "john-doe-123",
"count": 20,
"server_call": false,
"min_delay": 0.5,
"max_delay": 1.5
}
Parameters:
| Parameter | Type | Description |
|---|---|---|
profile_id |
string | LinkedIn profile ID or full profile URL |
count |
integer | Number of comments to fetch (-1 for all, max: 200) |
server_call |
boolean | Execution mode (false: proxy, true: server) |
min_delay |
float | Min delay between pagination requests (seconds, default: 0.5) |
max_delay |
float | Max delay between pagination requests (seconds, default: 1.5) |
Response:
{
"data": [
{
"commentText": "Great insights! Thanks for sharing.",
"commentId": "urn:li:comment:(7123456789,urn:li:activity:7123456780)",
"postText": "Here's my latest article on AI...",
"postUrl": "https://linkedin.com/feed/update/urn:li:activity:7123456780",
"parentCommentText": null,
"parentCommentId": null,
"parentCommenterName": null,
"parentCommenterHeadline": null,
"parentCommenterProfileId": null,
"isReply": false,
"replyToUserCommentText": null,
"replyToUserCommentId": null
},
{
"commentText": "I agree with your point about automation.",
"commentId": "urn:li:comment:(7123456790,urn:li:activity:7123456781)",
"postText": "Discussion about the future of work...",
"postUrl": "https://linkedin.com/feed/update/urn:li:activity:7123456781",
"parentCommentText": "Automation is changing everything.",
"parentCommentId": "urn:li:comment:(7123456788,urn:li:activity:7123456781)",
"parentCommenterName": "Jane Smith",
"parentCommenterHeadline": "Tech Lead at AI Corp",
"parentCommenterProfileId": "ACoAACXyz123...",
"isReply": true,
"replyToUserCommentText": null,
"replyToUserCommentId": null
}
]
}
π‘ Comment Context
This endpoint provides rich context for each comment:
- β’ Root Comments: Direct comments on posts (
isReply: false) - β’ Reply Comments: Replies to other comments (
isReply: true) - β’ Post Context: Full post text and URL for each comment
- β’ Parent Details: When it's a reply, includes parent comment and commenter info
- β’ Hard Limit: Maximum 200 comments to prevent excessive API calls
π Interactive Documentation
Once the server is running, visit the interactive API documentation:
- β’ Swagger UI: http://localhost:8000/docs
- β’ ReDoc: http://localhost:8000/redoc
π’ Deployment
Production Deployment Options
1. Docker Compose (Recommended)
- β’ Complete setup in
deployment/folder - β’ Includes PostgreSQL, backend, health checks
- β’ One-command deployment
- β’ See
deployment/README.md
2. VPS/Self-Hosted
- β’ Ubuntu/Debian server
- β’ Nginx reverse proxy
- β’ Let's Encrypt SSL certificates
- β’ Systemd service management
3. Cloud Platforms
- β’ Heroku, Railway, Render
- β’ One-click deployment
- β’ Managed PostgreSQL
- β’ Auto-scaling
Environment Variables
Key environment variables (see backend/.env.example):
# Database
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your_password
DB_NAME=LinkedinGateway
# API
API_HOST=0.0.0.0
API_PORT=8000
# JWT
JWT_SECRET_KEY=your_secret_key
JWT_ALGORITHM=HS256
JWT_EXPIRATION_MINUTES=10080
# LinkedIn OAuth
LINKEDIN_CLIENT_ID=your_client_id
LINKEDIN_CLIENT_SECRET=your_client_secret
LINKEDIN_REDIRECT_URI=https://your-domain.com/auth/user/callback
# CORS
CORS_ORIGINS=*
# Rate Limiting
DEFAULT_RATE_LIMIT=100
DEFAULT_RATE_WINDOW=3600
HTTPS Setup
β οΈ HTTPS Required
LinkedIn OAuth requires HTTPS. Available options:
- β’ Cloudflare Tunnel (Free, recommended for development)
- β’ Ngrok (Free tier available)
- β’ Nginx + Let's Encrypt (Self-hosted production)
- β’ Cloud Platform SSL (Managed)
See backend/HTTPS_TUNNELING_GUIDE.md for detailed setup instructions.
π Monitoring & Logging
Health Checks
| Endpoint | Description |
|---|---|
GET /health |
API health status |
GET /health/db |
Database connection health |
GET /api/ws/status |
WebSocket connection status |
Logging
Logs are written to:
- Console: Structured JSON logs
- File:
backend/logs/(if configured) - Docker:
docker-compose logs -f backend
Log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
π οΈ Technology Stack
Backend
- β’ FastAPI (Python 3.11+)
- β’ PostgreSQL 15
- β’ SQLAlchemy 2.0 (async)
- β’ Alembic (migrations)
- β’ JWT + LinkedIn OAuth 2.0
- β’ HTTPX (async)
Chrome Extension
- β’ Manifest V3
- β’ Webpack 5
- β’ JavaScript (ES6+)
- β’ HTML5, CSS3
- β’ Chrome Extension APIs
- β’ WebSocket API
Infrastructure
- β’ Docker & Docker Compose
- β’ Nginx (reverse proxy)
- β’ Uvicorn with Gunicorn
- β’ Health check endpoints
- β’ Structured logging
β οΈ Important Notes
βοΈ LinkedIn Terms of Service
This tool interacts with LinkedIn's internal APIs. Users are responsible for:
- β’ Complying with LinkedIn's Terms of Service
- β’ Respecting rate limits and usage policies
- β’ Not engaging in spam or abusive behavior
- β’ Understanding potential account risks
Rate Limiting
- Default: 100 requests per hour per API key
- Configurable: Per user settings
- Response: 429 status code when exceeded
- Retry: Automatic retry with exponential backoff recommended
Session Management
- LinkedIn sessions expire periodically
- Server mode requires session refresh
- Proxy mode uses browser's active session
- Automatic session refresh on 401/403 errors
π Support & Resources
Built with β€οΈ using FastAPI, PostgreSQL, and modern web technologies.
Β© 2025 AInnovate.tech. Educational and development purposes only.
This is an unofficial tool not affiliated with LinkedIn Corporation.
Comment Operations
POST
/api/v1/posts/get-commentersFetch commenters and comments from a LinkedIn post with pagination support.
Request Body:
Parameters:
post_url(string) - LinkedIn post URL or activity URNcount(integer) - Number of comments to fetch (-1 for all, default: -1)num_replies(integer) - Number of replies to fetch per comment (default: 0)server_call(boolean) - Execution modePOST
/api/v1/posts/post-commentPost a comment on a LinkedIn post.
Request Body:
Parameters:
post_url(string) - Full LinkedIn post URL, feed URL, or post ID (e.g., "activity:7123456789")comment_text(string) - Comment text to postserver_call(boolean) - Execution modeResponse:
POST
/api/v1/posts/reply-to-commentReply to an existing comment on a LinkedIn post.
Request Body:
Parameters:
comment_urn(string) - Comment URN (provided by get-commenters endpoint in commentUrn field)reply_text(string) - Reply text to postserver_call(boolean) - Execution modeResponse: