LinkedIn Scraper

Scrapes LinkedIn job postings using the JobSpy library (python-jobspy).

How to use it

  1. Hit Copy the whole skill.
  2. Claude: ⋯ → Download .md, then Customize → Skills → Add → Upload skill.
    ChatGPT: make a Project and paste it into Instructions.
    Neither? Paste it at the top of a new chat — it works for that chat.
  3. Describe your job in plain words. The AI follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit gooseworks-ai/goose-skills/skills/lead-generation/capabilities/linkedin-job-scraper#main ~/.claude/skills/linkedin-job-scraper

For one project only, change the path to .claude/skills/linkedin-job-scraper.

Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Show the full text172 lines
linkedin-job-scraper/SKILL.md172 lines5.6 KBpushed 96d agoRawView on GitHub

LinkedIn Scraper

Overview

This skill finds LinkedIn job postings by running tools/jobspy_scraper.py, a thin wrapper around the JobSpy library. It handles installation, parameter construction, execution, and result interpretation.

Quick Start

Install the dependency once (requires Python 3.10+):

python3.12 -m pip install -U python-jobspy --break-system-packages

Run the scraper:

python3.12 tools/jobspy_scraper.py \
  --search "software engineer" \
  --location "San Francisco, CA" \
  --results 25 \
  --output .tmp/jobs.csv

Results are saved as CSV and printed as a summary table.


Workflow

Step 1 — Understand the request

Identify from the user's message:

  • Search term — job title, role, or keyword (required)
  • Location — city, state, or "Remote" (optional but recommended)
  • Results wanted — default to 25 if not specified
  • Recencyhours_old filter if user wants recent posts (e.g. "last 48 hours")
  • Company filterlinkedin_company_ids if targeting a specific company
  • Full descriptions — set --fetch-descriptions if user needs job description text

If anything is ambiguous (e.g. "find AI jobs"), pick reasonable defaults and tell the user what you used.

Step 2 — Construct the command

Build the tools/jobspy_scraper.py command using the parameters below. Always save output to .tmp/ so it's disposable and easy to find.

python tools/jobspy_scraper.py \
  --search "<term>" \
  --location "<location>" \
  --results <N> \
  [--hours-old <N>] \
  [--fetch-descriptions] \
  [--company-ids <id1,id2>] \
  [--job-type fulltime|parttime|contract|internship] \
  [--remote] \
  --output .tmp/<descriptive_filename>.csv

Note: --hours-old and --easy-apply cannot be used together (LinkedIn API constraint).

Step 3 — Run the script

Execute the command. The script will print a progress message and a summary of results found.

If the script is not found at tools/jobspy_scraper.py, check whether the file needs to be created by reading skills/linkedin-job-scraper/scripts/jobspy_scraper.py and copying it to tools/.

Step 4 — Interpret and present results

After the run:

  • Report how many jobs were found
  • Show a brief table: Title | Company | Location | Salary | Posted
  • Note the output file path so the user can open it
  • If 0 results: suggest broadening the search term or removing the location filter

Parameters Reference

Flag Description Default
--search Job title / keywords required
--location City, state, or country none
--results Number of results to fetch 25
--hours-old Only jobs posted within N hours none
--fetch-descriptions Fetch full job descriptions (slower) false
--company-ids Comma-separated LinkedIn company IDs none
--job-type fulltime, parttime, contract, internship any
--remote Filter for remote jobs only false
--output Path for CSV output .tmp/jobs.csv

Output Columns

The CSV output includes:

Column Description
TITLE Job title
COMPANY Employer name
LOCATION City / State / Country
IS_REMOTE True/False
JOB_TYPE fulltime, contract, etc.
DATE_POSTED When the listing was posted
MIN_AMOUNT Minimum salary
MAX_AMOUNT Maximum salary
CURRENCY Currency code
JOB_URL Direct link to the LinkedIn posting
DESCRIPTION Full job description (if --fetch-descriptions used)
JOB_LEVEL Seniority level (LinkedIn-specific)
COMPANY_INDUSTRY Industry classification

Common Use Cases

Find recent engineering roles at a startup:

python tools/jobspy_scraper.py --search "growth engineer" --location "New York" \
  --results 50 --hours-old 72 --output .tmp/growth_eng_nyc.csv

Monitor what a specific company is hiring for:

# First find the LinkedIn company ID from the company's LinkedIn URL
python tools/jobspy_scraper.py --search "engineer" --company-ids 1234567 \
  --results 100 --fetch-descriptions --output .tmp/company_hiring.csv

Find remote contract roles:

python tools/jobspy_scraper.py --search "data analyst" --remote \
  --job-type contract --results 30 --output .tmp/remote_contracts.csv

Error Handling

Error Fix
ModuleNotFoundError: jobspy Run pip install -U python-jobspy
0 results returned Broaden search term, remove location, increase --results
Rate limited / blocked Wait a few minutes; avoid running back-to-back large scrapes
hours_old and easy_apply cannot both be set Remove one of those flags

Script Location

The scraper script lives at tools/jobspy_scraper.py.

If it doesn't exist, copy it from skills/linkedin-scraper/scripts/jobspy_scraper.py to tools/:

cp skills/linkedin-job-scraper/scripts/jobspy_scraper.py tools/
1---
2name: linkedin-job-scraper
3description: >
4 Scrapes LinkedIn job postings using the JobSpy library (python-jobspy). Use this skill
5 whenever the user wants to find jobs on LinkedIn, search for open roles, pull job listings,
6 build a job pipeline, source job targets for GTM research, or monitor hiring signals.
7 Even if the user just says "find me some jobs" or "what roles is [company] hiring for",
8 use this skill. It runs a local Python script that outputs a CSV of job postings with
9 title, company, location, salary, job type, description, and direct URLs.
10tags: [lead-generation]
11---
12 
13# LinkedIn Scraper
14 
15## Overview
16 
17This skill finds LinkedIn job postings by running `tools/jobspy_scraper.py`, a thin wrapper
18around the [JobSpy](https://github.com/speedyapply/JobSpy) library. It handles installation,
19parameter construction, execution, and result interpretation.
20 
21## Quick Start
22 
23**Install the dependency once (requires Python 3.10+):**
24```bash
25python3.12 -m pip install -U python-jobspy --break-system-packages
26```
27 
28**Run the scraper:**
29```bash
30python3.12 tools/jobspy_scraper.py \
31 --search "software engineer" \
32 --location "San Francisco, CA" \
33 --results 25 \
34 --output .tmp/jobs.csv
35```
36 
37Results are saved as CSV and printed as a summary table.
38 
39---
40 
41## Workflow
42 
43### Step 1 — Understand the request
44 
45Identify from the user's message:
46- **Search term** — job title, role, or keyword (required)
47- **Location** — city, state, or "Remote" (optional but recommended)
48- **Results wanted** — default to 25 if not specified
49- **Recency**`hours_old` filter if user wants recent posts (e.g. "last 48 hours")
50- **Company filter**`linkedin_company_ids` if targeting a specific company
51- **Full descriptions** — set `--fetch-descriptions` if user needs job description text
52 
53If anything is ambiguous (e.g. "find AI jobs"), pick reasonable defaults and tell the user what you used.
54 
55### Step 2 — Construct the command
56 
57Build the `tools/jobspy_scraper.py` command using the parameters below.
58Always save output to `.tmp/` so it's disposable and easy to find.
59 
60```bash
61python tools/jobspy_scraper.py \
62 --search "<term>" \
63 --location "<location>" \
64 --results <N> \
65 [--hours-old <N>] \
66 [--fetch-descriptions] \
67 [--company-ids <id1,id2>] \
68 [--job-type fulltime|parttime|contract|internship] \
69 [--remote] \
70 --output .tmp/<descriptive_filename>.csv
71```
72 
73**Note:** `--hours-old` and `--easy-apply` cannot be used together (LinkedIn API constraint).
74 
75### Step 3 — Run the script
76 
77Execute the command. The script will print a progress message and a summary of results found.
78 
79If the script is not found at `tools/jobspy_scraper.py`, check whether the file needs to be created
80by reading `skills/linkedin-job-scraper/scripts/jobspy_scraper.py` and copying it to `tools/`.
81 
82### Step 4 — Interpret and present results
83 
84After the run:
85- Report how many jobs were found
86- Show a brief table: Title | Company | Location | Salary | Posted
87- Note the output file path so the user can open it
88- If 0 results: suggest broadening the search term or removing the location filter
89 
90---
91 
92## Parameters Reference
93 
94| Flag | Description | Default |
95|------|-------------|---------|
96| `--search` | Job title / keywords | required |
97| `--location` | City, state, or country | none |
98| `--results` | Number of results to fetch | 25 |
99| `--hours-old` | Only jobs posted within N hours | none |
100| `--fetch-descriptions` | Fetch full job descriptions (slower) | false |
101| `--company-ids` | Comma-separated LinkedIn company IDs | none |
102| `--job-type` | fulltime, parttime, contract, internship | any |
103| `--remote` | Filter for remote jobs only | false |
104| `--output` | Path for CSV output | .tmp/jobs.csv |
105 
106---
107 
108## Output Columns
109 
110The CSV output includes:
111 
112| Column | Description |
113|--------|-------------|
114| `TITLE` | Job title |
115| `COMPANY` | Employer name |
116| `LOCATION` | City / State / Country |
117| `IS_REMOTE` | True/False |
118| `JOB_TYPE` | fulltime, contract, etc. |
119| `DATE_POSTED` | When the listing was posted |
120| `MIN_AMOUNT` | Minimum salary |
121| `MAX_AMOUNT` | Maximum salary |
122| `CURRENCY` | Currency code |
123| `JOB_URL` | Direct link to the LinkedIn posting |
124| `DESCRIPTION` | Full job description (if --fetch-descriptions used) |
125| `JOB_LEVEL` | Seniority level (LinkedIn-specific) |
126| `COMPANY_INDUSTRY` | Industry classification |
127 
128---
129 
130## Common Use Cases
131 
132**Find recent engineering roles at a startup:**
133```bash
134python tools/jobspy_scraper.py --search "growth engineer" --location "New York" \
135 --results 50 --hours-old 72 --output .tmp/growth_eng_nyc.csv
136```
137 
138**Monitor what a specific company is hiring for:**
139```bash
140# First find the LinkedIn company ID from the company's LinkedIn URL
141python tools/jobspy_scraper.py --search "engineer" --company-ids 1234567 \
142 --results 100 --fetch-descriptions --output .tmp/company_hiring.csv
143```
144 
145**Find remote contract roles:**
146```bash
147python tools/jobspy_scraper.py --search "data analyst" --remote \
148 --job-type contract --results 30 --output .tmp/remote_contracts.csv
149```
150 
151---
152 
153## Error Handling
154 
155| Error | Fix |
156|-------|-----|
157| `ModuleNotFoundError: jobspy` | Run `pip install -U python-jobspy` |
158| 0 results returned | Broaden search term, remove location, increase `--results` |
159| Rate limited / blocked | Wait a few minutes; avoid running back-to-back large scrapes |
160| `hours_old and easy_apply cannot both be set` | Remove one of those flags |
161 
162---
163 
164## Script Location
165 
166The scraper script lives at `tools/jobspy_scraper.py`.
167 
168If it doesn't exist, copy it from `skills/linkedin-scraper/scripts/jobspy_scraper.py` to `tools/`:
169```bash
170cp skills/linkedin-job-scraper/scripts/jobspy_scraper.py tools/
171```
172 

Discussion

Alternatives

Also in Language patterns