A Chrome extension (Manifest V3) that:
- Reads the text of the open web page (or a PDF, either open in the browser or uploaded from your computer);
- Sends it to an AI model (a local model via Ollama, Anthropic Claude, or any OpenAI-compatible API) asking it to extract the relevant job posting fields (company, title, salary, work mode, deadline, etc.) in structured format;
- Shows the extracted fields in a small editable form before saving;
- Saves the row to a Google Sheet or a local CSV file (your choice, see "Data Destination") that acts as a "database" of all collected postings.
You pick the destination once in the extension Options. The local CSV option never sends your data to Google (no account or setup needed): only your chosen AI provider sees the posting text for extraction. The Google Sheet option appends to an online spreadsheet you share with your account. Keys/credentials remain stored only locally in your browser (chrome.storage.sync).
Which steps you need depends only on your destination. Steps 1, 2, and 5 are always needed; the Google-specific steps (3 and 4) are skipped entirely if you choose local CSV.
| Step | Local CSV | Google Sheet |
|---|---|---|
| 1. Install the extension | needed | needed |
| 2. Configure the AI provider | needed | needed |
| 3. Configure Google Sheets access (OAuth) | skip | needed |
| 4. Create the destination Google Sheet | skip | needed |
| 4b. Pick a local CSV file | needed | skip |
| 5. Field schema (optional tuning) | optional | optional |
- Fastest path (local CSV): do 1 → 2 → 4b. No Google account, no OAuth, no cloud project.
- Google Sheets path: do 1 → 2 → 3 → 4.
- Open Chrome and go to
chrome://extensions. - Enable "Developer mode" (toggle in the top right).
- Click "Load unpacked" and select the
jobclipfolder (this folder). - The extension will appear in the list named "JobClip". Note the extension ID (a 32-character string shown below the name): you'll need it in step 3.
At this point the extension is installed but not yet configured: you need to set the AI provider API key and pick a data destination (a Google Sheet or a local CSV file).
The extension supports two provider types; for a fully private, offline setup you can also run the model locally with Ollama (described at the end of this section).
- In the extension Options, select "OpenAI Compatible" as provider.
- Enter the chat completions endpoint URL. Examples:
- Z.ai:
https://api.z.ai/api/coding/paas/v4/chat/completionsfor the Coding Plan. - OpenAI:
https://api.openai.com/v1/chat/completions
- Z.ai:
- Enter your API key and model name (e.g.
glm-5.1,gpt-4o,llama-3.3-70b).
- Go to https://console.anthropic.com/settings/keys and create an API key (an Anthropic account with credit/payment method is required; extracting one posting costs a fraction of a cent with the Haiku model).
- Click the extension icon in the Chrome toolbar, then the gear icon in the top right of the popup (or right-click the extension icon -> "Options").
- Select "Anthropic (Claude)" as provider and paste the API key. The default model (Claude Haiku 4.5) is recommended: fast and cheap. You can switch to Sonnet 4.6 if extraction is imprecise on complex postings.
Ollama runs an LLM on your own computer. Because it speaks the same OpenAI-compatible protocol as the providers above, you configure it in the extension as "OpenAI Compatible", but the posting text never leaves your machine. Combined with the local CSV destination, this gives you a completely offline pipeline: no cloud account, no API billing, no third party seeing the data.
Setup:
-
Install and start Ollama (see https://ollama.com).
-
Pull a model that follows JSON instructions reliably, larger models extract more accurately:
ollama pull gemma4:26bVery small models often fail at structured JSON output; prefer 7B+ sizes for this task. But beware: without a GPU, large models might be painfully slow.
-
By default Ollama refuses requests originating from a browser (like this extension), so it must be explictily told to accept them via CORS. Set the
OLLAMA_ORIGINSenvironment variable tochrome-extension://*before launching it, following this guide. -
In the extension Options, select OpenAI Compatible as the provider and enter:
- Endpoint:
http://localhost:11434/v1/chat/completions - API key: any non-empty placeholder, e.g.
ollama(Ollama ignores it, but the extension requires a value to be present). - Model: the exact name of the model you pulled, e.g.
llama3.3(runollama listto confirm).
- Endpoint:
-
Save settings. The first extraction loads the model into memory and can take several seconds; later ones are faster.
Google Sheet destination only. If you save to a local CSV file, skip this entire section and go to §4.
This is the most "technical" step but only needs to be done once.
- Go to https://console.cloud.google.com/ and create a new project (or use an existing one).
- In the menu, go to APIs & Services -> Library, search for "Google Sheets API" and click Enable.
- Go to APIs & Services -> OAuth consent screen.
- User type: External is fine for personal use.
- Fill in the required fields (app name, support email, etc.); you can use generic data, it's for personal use only.
- In the Scopes section, add the scope
https://www.googleapis.com/auth/spreadsheets. - In the Test users section, add your Gmail address (while the app is in "Testing" status, only listed test users can authorize it).
- Go to APIs & Services -> Credentials -> Create credentials -> OAuth client ID.
- As "Application type" choose Chrome Extension.
- In "Item ID" enter the extension ID you noted in step 1 (32 characters).
- Create the credentials: you'll get a Client ID like
1234567890-abcdefg.apps.googleusercontent.com.
- Open the
manifest.jsonfile of this extension with a text editor. - Replace the placeholder value:
with the Client ID obtained in step 3.3.
"oauth2": { "client_id": "INSERT_YOUR_CLIENT_ID_HERE.apps.googleusercontent.com", ... }
- Go back to
chrome://extensionsand click the reload icon of the extension to apply the change.
Note: if you uninstall and reinstall the "unpacked" extension from a different folder in the future, the extension ID might change, in which case it must be updated in Google Cloud Console (step 3.3) and the authorization flow must be repeated.
Google Sheet destination only. Not needed for the local CSV path.
- Create a new Google Sheet (it can be empty, column headers are created automatically on first save).
- Copy the sheet ID from the URL:
https://docs.google.com/spreadsheets/d/ID_HERE/edit - In the extension Options (gear icon), paste the ID in the "Google Sheet ID" field and optionally customize the tab name (default "Job Postings").
- Save settings.
The first time you save a posting, Chrome will ask you to authorize the extension to access Google Sheets with your account: accept (you may see an "unverified app" warning because the app is in test mode - this is normal for personal projects, click "Advanced" -> "Go to... (unsafe)" to proceed).
If you prefer not to set up Google Cloud OAuth — or just want the data to stay on your computer — use the local CSV destination.
- Open the extension Options and, under Data Destination, choose Local CSV file (private).
- Click Choose CSV file… and pick where to save it. A brand-new file is fine: the column header row is created automatically on the first save.
- Save settings. The same file is appended to on every save, so you build up one CSV "database" over time.
Notes:
- Only the columns defined by your field schema are written, in order (same as the Google Sheets flow). The first row is the header.
- The browser stores a reference (file handle) to that file; it does not get a copy. The file is only read/written when you save.
- The first save after starting Chrome may show a one-time permission prompt asking for access to the file -> accept it to continue. This is a Chrome security requirement, not part of the extension.
- If you edit the CSV's header row by hand (rename or remove a column), the next save will stop with a clear error rather than corrupt the file: align the header with the schema, or pick a new file in Options.
- To switch back to Google Sheets at any time, change the destination in Options and paste your Sheet ID (sections §3 and §3b). Both destinations can coexist in your settings; only the selected one is used.
The extension uses a JSON schema to define which fields are extracted and saved. You can fully customize it from the Options page.
The schema is a JSON array of field objects:
[
{
"name": "company",
"label": "Company / Organization",
"type": "text",
"placeholder": "e.g. Acme Corp",
"aiDescription": "name of the company or organization posting the job",
"readonly": false,
"auto": false
},
{
"name": "experience_level",
"label": "Experience Level",
"type": "select",
"options": [
{ "value": "not_specified", "label": "Not specified" },
{ "value": "junior", "label": "Junior" },
{ "value": "mid", "label": "Mid" },
{ "value": "senior", "label": "Senior" }
],
"aiDescription": "one of: junior, mid, senior, not_specified",
"readonly": false,
"auto": false
}
]| Property | Required | Description |
|---|---|---|
name |
Yes | Internal identifier. Used as column header in Google Sheets and form field name. |
label |
Yes | Display label shown in the popup form. |
type |
Yes | Input type: text, textarea, select, or date. |
options |
For select |
Array of {value, label} objects defining the dropdown options. |
placeholder |
No | Placeholder text for the input field. |
aiDescription |
No | Description included in the AI extraction prompt. Fields without this won't be extracted by AI. |
readonly |
No | If true, the field is read-only in the form. |
auto |
No | If true, the value is auto-generated (not sent to AI for extraction). |
The default schema includes three auto-generated fields:
- save_date - set to the current date when saving
- source - hostname extracted from the posting URL
- url - the full page URL
You can remove or modify these, or add new auto fields. Custom auto fields will be left empty unless you also modify the popup logic.
- Open the extension Options page.
- Scroll to the "Field Schema" section.
- Edit the JSON in the textarea.
- Click "Save settings". The schema is validated before saving.
- Use "Reset to default" to restore the original schema.
- Open the job posting in the active tab.
- Click the extension icon -> "Extract from current page".
- Wait a few seconds (page reading + AI call).
- Review/edit the pre-filled fields in the form.
- Click "Save to Google Sheet" (or "Save to CSV file", depending on your chosen destination).
If the PDF is open as a browser tab (e.g. you clicked a PDF link), it works the same way: click "Extract from current page" and the extension will download and process the PDF.
Click "Upload a PDF from your computer" and select the file: text is extracted locally (no file upload, only the extracted text is sent to the AI model for structuring).
Each row in the Google Sheet contains columns defined by your field schema. The default schema includes:
| Column | Description |
|---|---|
| save_date | Date you saved the posting |
| company | Company/organization name |
| job_title | Position title |
| experience_level | junior / mid / senior / lead_manager / not_specified |
| contract_type | e.g. permanent, fixed-term, internship... |
| work_mode | remote / hybrid / onsite / not_specified |
| location | City/country |
| salary_min | Minimum annual salary (number) |
| salary_max | Maximum annual salary (number) |
| currency | EUR, USD, etc. |
| salary_notes | Notes on compensation/benefits |
| publish_date | Posting publish date |
| deadline | Application deadline |
| skills | List of skills/technologies |
| summary | Brief position summary |
| notes | Other relevant information |
| source | Website domain (e.g. linkedin.com) |
| url | Full posting URL |
| other | Other notes on the position |
| applied_for | Whether an application process was started or not (default: false) |
You can add custom columns by editing the field schema. You can also manually add columns directly in the Google Sheet (e.g. "application_status", "cv_sent_date", "priority") without the extension overwriting them: the append only adds the schema-defined columns in order.
- AI extraction can make mistakes, especially on poorly structured or very long postings: always review fields before saving.
- Pages protected by complex login (e.g. some LinkedIn sections behind paywall) may show only a preview of the text: extraction works on the actually visible text.
- Very long PDFs are read only in the first 15 pages (usually sufficient for a job posting).
- The extension doesn't work on
chrome://pages, the Web Store, or other browser "protected" pages (Chrome security limitation). - For PDFs opened from local files (
file:///...pdf), Chrome requires manually enabling "Allow access to file URLs" in the extension details (chrome://extensions-> JobClip -> Details).