Skip to content

Sumit884-byte/linkedin_connection_bot

Repository files navigation

LinkedIn Connection Bot

Automate LinkedIn people search and send connection requests on a daily cap. New contacts are appended to a CSV for outreach tracking. Runs headless on a schedule (macOS) or interactively via CLI or GUI.

Built with Python, Selenium, and Brave (or another Chromium-based browser). Optional OpenTelemetry export to a local SigNoz stack.


What it does

  1. Logs into LinkedIn with credentials from .env
  2. Searches people by semicolon-separated keywords (e.g. TCS;Accenture;Wipro) with optional location filters
  3. Sends connection requests up to a per-run limit, skipping profiles already in the CSV
  4. Falls back to My Network → Grow when search results are exhausted
  5. Writes results to OutputFolder/dataset.csv and can resume across runs via OutputFolder/run_state.json

Features

  • CLI or GUIrun_bot.py for unattended runs; Run_me.py for a desktop launcher
  • Brave-first — detects and uses your system default browser (Brave, Chrome, Edge, Firefox, Safari)
  • Profile reuse — optionally copies cookies from your existing browser profile so you may already be logged in
  • Connection limits — cap invites per run; daily scheduling sends at most once per calendar day
  • Grow fallback — continues from My Network when people search runs out of Connect buttons
  • CSV deduplication — appends to OutputFolder/dataset.csv and skips known profiles
  • ChromeDriver auto-fix — detects version mismatches, downloads a matching driver, and retries
  • SigNoz observability — optional traces, metrics, and correlated logs (see below)

Requirements

Requirement Notes
Python 3.10+ Tested on macOS
Brave Browser (recommended) Or Chrome / Edge (Chromium-based). Firefox and Safari are supported with limitations.
ChromeDriver Handled automatically via webdriver-manager. Manual install is not required.
LinkedIn account Credentials go in .env (never commit this file).
Docker Desktop (optional) Only needed for the local SigNoz stack.

Quick start

1. Clone and set up Python

git clone https://github.com/Sumit884-byte/linkedin_connection_bot.git
cd linkedin_connection_bot

python3 -m venv venv
source venv/bin/activate        # macOS / Linux
# venv\Scripts\activate         # Windows

pip install -r requirements.txt

2. Configure .env

cp .env.example .env

Edit .env with your credentials and search settings:

LINKEDIN_USERNAME=your_email@example.com
LINKEDIN_PASSWORD=your_password
LINKEDIN_FIELDS=accenture;software engineer
LINKEDIN_LOCATION=
LINKEDIN_CONNECTIONS=10
LINKEDIN_BROWSER=brave

See Configuration for all variables.

3. Run the bot

CLI (recommended for scheduled / headless runs):

python run_bot.py

GUI:

python Run_me.py

Fill in the fields (or rely on values from .env) and click Start The Automation!!


Run automatically on macOS

The bot can run once per calendar day while your Mac is on — no fixed clock time.

How it works

  • Runs when you log in after turning the Mac on
  • Re-checks every hour while the Mac stays on (skips if it already ran successfully today)
  • Uses a lock file (OutputFolder/.daily_run.lock) to avoid overlapping runs
  • Retries once with ChromeDriver auto-fix if the first attempt fails

1. Configure .env for unattended runs

BROWSER_HEADLESS=true
USE_BROWSER_PROFILE=true
LINKEDIN_BROWSER=brave
USE_NETWORK_GROW=true

LINKEDIN_START_WITH_GROW=true is useful if the previous run already exhausted people search and you want to skip straight to Grow.

2. Install the launchd job

chmod +x schedule/install_daily_schedule.sh schedule/daily_run.sh
./schedule/install_daily_schedule.sh install

Optional: change the hourly check interval (seconds, minimum 300):

DAILY_CHECK_INTERVAL_SECONDS=1800 ./schedule/install_daily_schedule.sh install

3. Test manually

./schedule/daily_run.sh

Logs: OutputFolder/logs/daily-YYYY-MM-DD.log
Launchd stdout/stderr: OutputFolder/logs/launchd.out.log, launchd.err.log

Force another run the same day:

FORCE_DAILY_RUN=1 ./schedule/daily_run.sh

Manage the schedule

./schedule/install_daily_schedule.sh status
./schedule/install_daily_schedule.sh uninstall

Configuration

All settings can live in .env. Defaults below are what the code uses when a variable is unset (your .env.example may differ).

Variable Description Default
LINKEDIN_USERNAME LinkedIn email
LINKEDIN_PASSWORD LinkedIn password
LINKEDIN_FIELDS Search keywords, semicolon-separated
LINKEDIN_LOCATION Location filters, semicolon-separated. Empty = no filter.
LINKEDIN_CONNECTIONS Max invites per run (0 = no limit) 10
LINKEDIN_PAGES Search result pages per keyword 1
LINKEDIN_BROWSER auto, brave, chrome, edge, firefox, safari auto
USE_BROWSER_PROFILE Copy cookies from your real browser profile true
BROWSER_HEADLESS Run without a visible browser window false
USE_NETWORK_GROW After search is exhausted, connect from Grow true
LINKEDIN_START_WITH_GROW Skip people search; connect only from Grow false
LINKEDIN_RESUME On re-run, continue from Grow if search was already exhausted true
AUTO_ACCEPT_INVITATIONS Accept pending incoming invites on Grow before sending new requests true
LINKEDIN_IMPLICIT_WAIT Element lookup timeout (seconds) 2
LINKEDIN_CARD_DELAY Pause after each connection (seconds) 0.8
LINKEDIN_ACTION_DELAY Pause between small UI actions (seconds) 0.3
LINKEDIN_DRIVER_AUTO_FIX_ATTEMPTS Max ChromeDriver auto-fix retries per launch 2
SIGNOZ_ENABLED Export traces, metrics, and logs to SigNoz false
OTEL_EXPORTER_OTLP_ENDPOINT SigNoz OTLP gRPC endpoint http://localhost:4317
OTEL_SERVICE_NAME Service name in SigNoz linkedin-connection-bot
OTEL_DEPLOYMENT_ENVIRONMENT Environment label (local, prod, …) local

GUI fields map to the same settings: Keywords → LINKEDIN_FIELDS, Pages → LINKEDIN_PAGES, Location → LINKEDIN_LOCATION.


Output

Connections are written to:

OutputFolder/dataset.csv

Copy the example header if the file does not exist yet:

cp OutputFolder/dataset.csv.example OutputFolder/dataset.csv

Columns: Name, Headline, Location, Profile URL

The file is appended on each run. Profiles already present are skipped automatically. Resume state between runs is stored in OutputFolder/run_state.json (gitignored).


SigNoz observability (optional)

The bot exports OpenTelemetry traces, metrics, and correlated logs to a local SigNoz stack when enabled.

1. Start SigNoz

Prerequisite: Docker Desktop must be running.

open -a Docker   # macOS — if `docker info` fails
docker compose -f pours/deployment/compose.yaml up -d

Wait ~30–60s, then verify:

docker compose -f pours/deployment/compose.yaml ps
curl -s http://localhost:8080/api/v1/health   # expect {"status":"ok"}
Endpoint URL
SigNoz UI http://localhost:8080
OTLP gRPC ingest localhost:4317
# Stop (keeps data volumes)
docker compose -f pours/deployment/compose.yaml down

# Restart after Docker Desktop reboot
docker compose -f pours/deployment/compose.yaml up -d

2. Enable telemetry in .env

SIGNOZ_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_SERVICE_NAME=linkedin-connection-bot
OTEL_DEPLOYMENT_ENVIRONMENT=local

If SIGNOZ_ENABLED=false, telemetry is a no-op and the bot runs normally.

3. Run and verify in SigNoz

python run_bot.py

In SigNoz:

  • Serviceslinkedin-connection-bot
  • Tracesbot.run, bot.login, bot.connect_from_grow, …
  • Metricsbot.connections_sent, bot.run_duration_seconds, bot.driver_errors
  • Logs → lines with run_id= and phase=

Dashboard queries and alert ideas: docs/signoz-dashboard.md.
Write-up of the observability setup: docs/blog-signoz-linkedin-bot.md.


Troubleshooting

ChromeDriver / browser version mismatch

After a Brave or Chrome update you may see errors like "This version of ChromeDriver only supports Chrome version X".

The bot tries to fix this automatically: it detects the mismatch, downloads a matching driver via webdriver-manager, kills stale bot browser processes, and retries (up to LINKEDIN_DRIVER_AUTO_FIX_ATTEMPTS times). The daily scheduler also retries once after auto-fix.

If it still fails, confirm LINKEDIN_BROWSER matches the browser you have installed (e.g. brave) and restart Docker/your terminal so no old chromedriver processes linger.

Headless runs and LinkedIn checkpoints

LinkedIn may show CAPTCHA or security challenges. In headless mode there is no window to complete them.

  • Set BROWSER_HEADLESS=false, run once, complete the checkpoint manually, then re-enable headless.
  • With USE_BROWSER_PROFILE=true, a successful interactive login is copied into the bot's isolated profile for later headless runs.

Stale lock file or stuck browser

If a run is killed mid-flight, you may see "Another bot run is already in progress" or orphaned Brave windows titled with LinkedInBot.

  • The daily script removes a stale lock when the PID is no longer running.
  • Manually: delete OutputFolder/.daily_run.lock and quit any Brave-Browser-LinkedInBot (or similar) processes in Activity Monitor.
  • ./schedule/daily_run.sh calls cleanup_stale_bot_processes() before each run.

Missed clicks or slow UI

Raise delays in .env:

LINKEDIN_CARD_DELAY=1.5
LINKEDIN_IMPLICIT_WAIT=3

Not enough connections per run

One search page may not have enough Connect buttons. Increase LINKEDIN_PAGES or rely on USE_NETWORK_GROW=true to continue from Grow after search is exhausted.

SigNoz shows no data

Symptom Fix
connect: no such file or directory on docker.sock Start Docker Desktop (open -a Docker)
Nothing on port 8080 docker compose -f pours/deployment/compose.yaml up -d
UI not ready Wait until signoz-signoz-0 is (healthy) in docker compose ps
Bot runs but no telemetry Confirm SIGNOZ_ENABLED=true and OTLP endpoint http://localhost:4317

Project structure

linkedin_connection_bot/
├── run_bot.py                 # CLI entry point (.env → automation)
├── Run_me.py                  # GUI entry point
├── Scripts/
│   ├── selenium_Funct.py      # Core automation logic
│   ├── browser_utils.py       # Browser detection, launch, ChromeDriver auto-fix
│   ├── telemetry.py           # OpenTelemetry / SigNoz export
│   ├── graphical_script.py    # Tkinter GUI
│   └── constants.py           # Legacy defaults (overridden by .env)
├── schedule/
│   ├── daily_run.sh           # Once-per-day runner (used by launchd)
│   └── install_daily_schedule.sh
├── pours/deployment/          # Local SigNoz stack (docker compose)
├── docs/
│   ├── signoz-dashboard.md    # Example queries and alerts
│   └── blog-signoz-linkedin-bot.md
├── OutputFolder/
│   ├── dataset.csv.example    # CSV header template
│   ├── dataset.csv            # Exported contacts (runtime, gitignored)
│   └── logs/                  # Daily and launchd logs (gitignored)
├── .env.example
└── requirements.txt

Disclaimer

This tool automates actions on LinkedIn. Use it responsibly and in line with LinkedIn's Terms of Service and applicable laws. Automated connection requests can trigger account restrictions. The authors are not responsible for misuse or resulting account actions.


Credits

Originally created by Prabal Jain. Fork maintained by Sumit884-byte.

License

See LICENSE.

About

Automate LinkedIn people search and send connection requests on a daily cap. New contacts are appended to a CSV for outreach tracking. Runs headless on a schedule (macOS) or interactively via CLI or GUI.

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages