Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

netsift

Turn your LinkedIn connections export into ranked candidate lists for any target audience — 100% locally.

You define who you're looking for in a small config file (job-title keywords, industries, things to ignore). netsift reads your own LinkedIn data export, scores every connection against your definition, and writes ranked, segmented candidate lists. Great for finding beta testers, design partners, hiring leads, sales prospects, interview subjects — anyone hiding in your network.

Built originally to find beta testers for a compliance/audit SaaS, then generalised. The shipped example config (config.example.yaml) is that compliance/founders/consultants setup — edit it to describe your audience.

Why not the LinkedIn API?

There is no official LinkedIn API or MCP that lets you read your own connections — that access was removed years ago. Third-party scrapers violate LinkedIn's ToS and risk getting your account banned. The clean, allowed path is LinkedIn's own data export, which you process yourself. That's what netsift does.

Privacy

netsift makes no network calls. Nothing leaves your machine — no API, no upload, no telemetry. Your export and the generated lists stay local, and the default .gitignore keeps them out of git.


1. Get your LinkedIn data

LinkedIn → Settings & Privacy → Data Privacy → Get a copy of your data → Connections → request. You'll get a Connections.csv (or a full-archive .zip containing it) in a few minutes. (Emails are only included for connections who opted to share them, so most will be blank — that's normal.)

2. Install

git clone https://github.com/kanylbullen/netsift.git
cd netsift
pip install -r requirements.txt      # just PyYAML (skip if you use a JSON config)

Requires Python 3.9+.

3. Run

# Point at the CSV, the export .zip, or the unzipped folder — all work:
python netsift.py --connections Connections.csv --config config.example.yaml --out out/
python netsift.py -c Complete_LinkedInDataExport.zip -k config.example.yaml -o out/ --top 50

Try it on the bundled fake data first:

python netsift.py -c examples/sample_connections.csv -k config.example.yaml -o out/

Output (in out/)

File What
report.md Per-segment ranked tables + a summary
top50.md Merged top-N across all segments (size = --top)
candidates_<KEY>.csv Full ranked list for each segment
all_scored.csv Every connection with its segment, score and matched signals
noise.csv Everything filtered out (recruiters etc.) — so nothing silently vanishes

Flags

Flag Default Meaning
-c, --connections Connections.csv, the export .zip, or a folder containing it
-k, --config your audience config (.yaml or .json)
-o, --out out output directory
--top 50 size of the merged top-N list
--per-segment 40 rows per segment in report.md (0 = all)

4. Define your own audience (the config)

Copy config.example.yaml, rename it, and edit. The whole model is just weighted keywords per segment, plus optional company signals, industry bonuses and a noise filter.

settings:
  industry_bonus: 1.5            # bonus added when a regulated industry matches
  search_company_for_keywords: true
  substring_match: false         # see "Matching" below

segments:
  - key: A
    name: Compliance / security
    priority: 1                  # lower = ranked higher in the merged top-N list
    keywords:
      ciso: 6                    # higher weight = stronger signal
      iso 27001: 6
      compliance: 5
      internrevis: 5             # stems work: matches "internrevisionschef"

company_signals:                 # extra weight when the COMPANY name matches
  - segment: C
    weight: 3
    label: firm
    match: [consulting, pwc, kpmg, deloitte]

industries:                      # company name -> label; adds industry_bonus
  finance: [bank, fintech, försäkring]

noise:                           # drop entirely (title OR company match)
  positions: [recruit, talent acquisition, headhunt]
  companies: [bbq, frisör]

How a connection is placed: its title (and company, by default) is matched against every segment's keywords; matching weights are summed; it's assigned to its highest-scoring segment. Add industry_bonus if the company is in a listed industry. If nothing matches → UNSURE. If a noise term matches → excluded.

Matching

By default netsift uses smart matching: short acronyms (≤3 chars like vd, cio, dpo, grc) match as whole words — so vd (Swedish "CEO") won't hit avdelning — while longer terms match as substrings/stems, so internrevis catches internrevisionschef and bank catches Swedbank. Set substring_match: true to force naive substring matching everywhere.

Keywords are case-insensitive and Unicode-aware (å ä ö work). Works in any language — just put the right terms in your config.


License

MIT — see LICENSE. Contributions and config recipes welcome.

About

Turn your LinkedIn connections export into ranked ICP candidate lists — 100% local, no API. Define your target audience in a config, get segmented candidate lists.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages