rodado ae66b83b5e Broaden software filter and add junior/intern filter
- Add lead, technical, consultant, solutions, product manager, IT manager
  to the software-role allowlist so relevant non-"software" titles pass
- Add JUNIOR_TITLE_RE to drop junior, intern, trainee, apprentice titles
2026-05-05 13:45:30 +02:00

linkme

Scrapes LinkedIn job listings into a local CSV. Run it daily, delete rows you've applied to.

Usage

bun fetch

No setup needed. Results are appended to jobs.csv — reruns are safe, already-seen jobs are skipped by ID.

Output

jobs.csv — one row per job:

column description
date_found date you ran the fetch
posted_at date the job was posted on LinkedIn
search which search config matched it
title job title
company hiring company
link canonical LinkedIn job URL

Open in any spreadsheet app. Delete rows as you apply or dismiss.

How it works

  • Paginated scraping — fetches up to 6 pages per search (150 jobs) with a 400 ms delay between pages to avoid rate limiting
  • Card-boundary-safe parsing — each job card is isolated before extracting fields, preventing content from adjacent cards bleeding into company or date values
  • Language filter — drops German (m/w/d, umlauts, gender-marked vocabulary) and French (H/F, accented characters) job titles automatically
  • Software-role filter — requires the title to contain a relevant term (software, developer, data, AI, backend, devops, platform, architect, etc.) — eliminates aviation, mechanical, and pharma-process roles that match "Engineer" broadly
  • Global deduplication — job IDs are indexed from the existing CSV on startup; jobs you've already seen are never re-added, even if you delete and re-run
  • 30-day recency — only fetches jobs posted in the last month (f_TPR=r2592000)

Configure searches

Edit config.ts:

const KEYWORDS = [
  "Software Engineer",
  "Full Stack Engineer",
  "Data Engineer",
  "AI Engineer",
  "Ruby on Rails",
  "Python",
  // add or remove freely
].join(" OR ");

export const searches: SearchConfig[] = [
  {
    label: "Basel (city)",
    keywords: KEYWORDS,
    geoId: "103383283",
    location: "Basel",
    workType: ["onsite", "hybrid"],
    timePosted: "month",
  },
];

geoId values for the Basel area:

  • 103383283 — Basel (city)
  • 90009885 — Basel Metropolitan Area
  • 107117530 — Basel-Country

You can also paste any LinkedIn search URL directly as url: instead of building from filters.

S
Description
No description provided
Readme
12 MiB
Languages
TypeScript 91%
Shell 9%