Skip to content

About

Free PDF tools for recruiters that run entirely in your browser: redact a CV, merge, split, compress, watermark, header & footer. Nothing is uploaded.

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Recruiter Tools — Free Tools

Nineteen document utilities for recruiters that run entirely in your browser. The CV never leaves your machine.

Merge two PDFs? Upload the CV. Redact a name? Upload it. Every day, candidate data — salaries, home addresses, right-to-work documents — gets dropped into whatever free tool comes up first on Google. Most of those services keep the file. Some train on it. Almost none of them are covered by the data agreement you signed with your client or your candidate.

These tools do the same jobs without the upload. They are a static web page. The file is opened by JavaScript running in your own tab, changed there, and handed back to you as a download. There is no server to send it to, because there is no server.

Live site: https://openrecruitertools.github.io/recruiter-tools/

Everything is one page: a grid of cards, filtered by category. Drop a file on a card, set the options, press Run, take the download. A deep link like /#tool=blind-cv goes straight to one tool.

The tools

Fifteen work today. Four are greyed on the dashboard with a badge, because doing them honestly needs a real office layout engine rather than a browser tab — an approximation would quietly move your page breaks in a document going to a client.

Tool Category In → out What it does Worth knowing
PDF Merge PDF .pdf (several) → .pdf Joins PDFs in the order you drop them Bookmarks, form fields and attachments are not carried across
PDF Split PDF .pdf → .pdf or .zip Keep a page range, remove pages, or burst every page into a zip Ranges outside the document are trimmed rather than refused; removing every page is refused
PDF Compress PDF .pdf → .pdf Re-encodes the JPEGs inside a heavy scan at a quality you choose A text-only PDF will not shrink — it says so and gives you the original back. JBIG2, CCITT and JPEG 2000 images are skipped
PDF to Word Conversions .pdf → .docx Not available in the browser Needs a desktop app. Rebuilding paragraphs, tables and styles from positioned glyphs needs a real layout engine
Blind CV PDF .pdf → .pdf Removes name, email, phone, LinkedIn and optionally pronouns, DOB, address, nationality The output is a picture of the CV: no longer selectable or searchable. Cannot read text inside a scan. Detail below
PDF Header/Footer PDF .pdf → .pdf Text in any of six slots, {page} and {pages} tokens, optional logo Draws over the page rather than making room. Latin characters only
PDF to Images PDF .pdf → .zip Renders every page to a PNG or JPEG One image per page in a zip; large documents are limited by your machine's memory
PDF Watermark PDF .pdf → .pdf Stamps text across every page: straight, diagonal or tiled A label, not a lock — removable in any PDF editor. Latin characters only
Remove PDF Password PDF .pdf → .pdf Unlocks a password-protected PDF, keeping the text intact You need the password. This removes a lock you are entitled to remove; it does not break one
Extract Text PDF .pdf → .txt Pulls the text out into a plain text file A scan has no text to pull out, and it says so rather than handing you an empty file. No OCR here
Cover Page PDF .pdf → .pdf Puts a branded front sheet on a candidate PDF Three layouts. Built-in PDF fonts, so Latin characters only
Word to PDF Conversions .doc/.docx → .pdf Not available in the browser Needs a desktop app. Line breaking, hyphenation and fonts decide where the pages break
PPTX to PDF Conversions .ppt/.pptx → .pdf Not available in the browser Needs a desktop app. Themes, masters, SmartArt and charts have to render as PowerPoint renders them
Excel to PDF Conversions .xls/.xlsx → .pdf Not available in the browser Needs a desktop app. Print areas, fit-to-page scaling and repeated headers decide what a sheet looks like on paper
Images to PDF Images images (several) → .pdf Combines images into one PDF, in the order you drop them PNG, JPEG, WebP, BMP and GIF
Excel to CSV Conversions .xlsx/.xls/.ods → .csv Turns one sheet of a spreadsheet into a CSV One sheet at a time. Formulas become their last calculated value
CSV to Excel Conversions .csv/.tsv/.txt → .xlsx Turns a CSV into a real .xlsx workbook The delimiter is detected; check the preview if your data has commas inside quoted fields
Compress Image Images image → same format Shrinks a photo or scan, keeping its format PNG is lossless, so the quality slider does nothing for one — only a max width shrinks it, and the tool says so
Merge Word Documents Documents .docx (several) → .docx Joins .docx files with a page break between them .docx only, not the older .doc

Every page carries the same line: This runs in your browser. Nothing is uploaded. And a second one: it works offline.

Privacy: no network requests, and here is the proof

This is the whole point, so it is not left as a promise.

  • The libraries are vendored, not linked. pdf.js, pdf-lib, JSZip and the rest are copies in vendor/, pinned with checksums in vendor/VERSIONS.md. No CDN, no Google Fonts, no analytics, no trackers, no cookies, no service worker. A page fetches this site's own files and nothing else.
  • It works with the network off. Load the page, disconnect, and every tool still runs. There is nothing for it to phone home to.
  • The build checks it. scripts/smoke.mjs opens the dashboard in a real headless browser, drives every available tool through its own card with a real file, and fails if the page makes a single request to any origin but its own. That runs on every push and every pull request. If someone adds a CDN link, CI goes red.
  • The redaction claim is checked too. The same script loads the blind CV back with pdf.js and asserts that no extractable text remains anywhere in it.

Nothing is stored either: no localStorage, no IndexedDB, no cookies. Close the tab and the file is gone from the browser.

Add your own tool

A tool is one file with one exported object. Copy src/tools/_template.js, register it in src/registry.js, add a test, run npm test && npm run smoke, open a pull request — the card, its drop zone, its options form, the progress bar and the download button are all rendered from what you declared.

CONTRIBUTING.md walks through all four steps, and states the three hard rules: it runs entirely in the browser, no telemetry, and any library must be permissively licensed (MIT / Apache-2.0 / BSD — no GPL or AGPL), vendored, and checksummed in vendor/VERSIONS.md.

The most useful thing you can send us is not code, though: which tool do you upload candidate data to today? The most-asked-for tool gets built next.

Putting the dashboard on another page

The whole dashboard is embeddable with one script tag and one container. That is how openrecruitertools.github.io shows it without copying a line of this repository.

<section data-free-tools></section>
<script type="module" src="/recruiter-tools/embed.js"></script>

The contract:

  • embed.js is the only stable entry point. It exports mountFreeTools(target, config?), plus tools and getTool from the registry, and auto-mounts into the first [data-free-tools] element on the page if there is one. Everything else in src/ is internal and may move.

  • Use an absolute, same-origin path for the src. Every asset the dashboard loads — its stylesheet, the vendored PDF libraries, the pdf.js worker — is resolved from import.meta.url, never from the page URL, so the same file works when the site is served at / and at /recruiter-tools/. It has to be same-origin because the module is a module and the workers are workers.

  • It brings its own CSS. dashboard.css is linked into <head> once, and everything is scoped to .free-tools, so it will not fight your stylesheet. Override the custom properties on .free-tools (--ft-bg, --ft-accent, --ft-card, --ft-border, …) if you want it in your own colours.

  • To mount it yourself, import it instead:

    <script type="module">
      import { mountFreeTools } from '/recruiter-tools/embed.js';
      mountFreeTools('#my-container', { title: 'Free Tools' });
    </script>

    config takes tools (a subset of the registry), title and disclaimer. It returns { element, destroy() }.

  • Deep links keep working: #tool=<id> scrolls to that card and highlights it, on whichever page the dashboard is embedded in.

  • It makes no network requests of its own beyond this site's files, so it does not change the privacy story of the page that embeds it.

How redaction works

A black rectangle drawn over a PDF is not redaction. The words are still in the file and anyone can copy them straight back out. That is how redaction failures end up in the news, and plenty of "redact PDF" tools do exactly that.

Genuinely deleting individual glyphs from a PDF content stream needs a full text engine and metrics for every embedded font. A half-working version of that is worse than nothing, because it looks redacted and is not.

There is a library that does it properly — MuPDF's WASM build has a real addRedaction / applyRedactions pair — but it is AGPL-3.0, which would make this whole site AGPL and is incompatible with keeping it MIT. See vendor/VERSIONS.md.

So this tool takes the route that can actually be guaranteed:

  1. pdf.js renders each page to a canvas and reports where every run of text sits.
  2. Matches are found in the page's text — the names you typed, plus patterns for emails, phones, URLs, LinkedIn handles and the optional categories — and mapped back to rectangles on the canvas.
  3. Those rectangles are painted onto the pixels. Gendered pronouns are handled differently: the word is covered in the paper colour and the neutral form (they / them / their) is written in its place.
  4. pdf-lib builds a brand-new PDF whose pages are those images.

What that guarantees

  • No text survives anywhere in the output. There are no text objects in the file at all — nothing to select, copy, search or recover, including text that was hidden, white-on-white, or underneath something else in the original.
  • None of the original metadata comes across. No title, author, producer or XMP; no bookmarks, attachments, annotations, form fields, JavaScript or embedded files. The output is a fresh document.
  • Nothing leaves your machine.

What it cannot guarantee

  • That it found everything. Detection is patterns plus the names you type. An unusual phone format, a different spelling, an initial, a personal website or a distinctive job title can all slip through. Look at the preview, every time.
  • Anything about scans. If the CV is a photograph of a document there is no text to find. The page is rebuilt exactly as it looked, name and all. There is no OCR here — and the tool warns you when it sees a page with no text.
  • Photographs. A profile photo is not removed in this version. Crop it first.
  • Exact placement. Boxes come from the positions pdf.js reports, spreading a run of text evenly across its characters. Occasionally a box catches a neighbouring letter, or a word hyphenated across two lines is only half matched.

The cost of the guarantee: the output is a picture. It is no longer selectable or searchable, an ATS cannot parse it, and it is usually larger than the original. That is the price of the text genuinely being gone, and it is the right trade for a blind CV going to a client.

Running it locally

No build step. It is HTML, two stylesheets, and ES modules.

git clone https://github.com/OpenRecruiterTools/recruiter-tools
cd recruiter-tools
npm install       # only needed for the tests and linter
npm run serve     # http://127.0.0.1:8080

A static server is required rather than opening index.html from the filesystem: pdf.js runs in a module worker, and browsers refuse to load one over file://. Any static server will do — python -m http.server works fine.

To work on the embed, serve both sites the way GitHub Pages does — the organisation home page at /, this repository at /recruiter-tools/:

npm run serve:both        # expects ../openrecruitertools.github.io
ORG_SITE=../elsewhere npm run serve:both

Node 20 or newer for the tooling.

Development

npm test              # vitest + jsdom
npm run test:contract # just the registry contract check
npm run lint          # eslint
npm run format:check  # prettier
npm run smoke         # drives every available tool in headless Chromium
npm run screenshots   # the dashboard and the org home page at 1280 into docs-screenshots/

npm test covers the parts worth testing on their own: the tool contract over every module in the registry, the dashboard's rendering and filtering, the redaction pattern finder and its overlap resolution, the page-range parser, the text-box and watermark geometry, size formatting, spreadsheet and text handling, and the options-to-run plumbing of each tool.

npm run smoke needs Chromium. It looks for playwright-core in PLAYWRIGHT_CORE, then in node_modules, then in a local npx cache; install one with npm i -D playwright-core && npx playwright install chromium.

Layout

index.html            the hero and the dashboard
embed.js              the stable entry point other pages import
dashboard.css         the dashboard's own stylesheet, scoped to .free-tools
styles.css            the page around it
tools/*.html          redirect stubs to /#tool=<id>, for the old per-tool URLs
src/
  registry.js           THE TOOL CONTRACT, and the list of tools in card order
  dashboard.js          renders the grid, the filters and the tool modal
  tools/                one file per tool — _template.js to copy, _shared.js helpers
  patterns.js           what to redact — pure, heavily tested
  ranges.js             page ranges — pure
  geometry.js           text boxes, watermark placement — pure
  format.js             sizes and names — pure
  redact.js             the flagship: render, paint, rebuild
  merge/split/compress/watermark/headerfooter.js
  ui.js                 shared drop-zone and download plumbing
  vendor.js             loads the vendored libraries
vendor/               pinned libraries + VERSIONS.md
tests/                vitest — tools/ mirrors src/tools/
scripts/              static servers, fixtures, smoke run, screenshots

Contributing

Issues and pull requests welcome, particularly from recruiters who are not programmers: try a tool on a real CV, and say where it confused you or what it missed. Bug reports about redaction misses are the most valuable thing you can file — please describe the shape of what was missed rather than pasting real candidate data.

Start with CONTRIBUTING.md. By taking part you agree to the Code of Conduct.

Still on the list: profile-photo removal in the blind CV, OCR for scans, and desktop companions for the four office conversions that cannot be done in a tab.

Licence

MIT — see LICENSE. Vendored libraries keep their own licences; see vendor/VERSIONS.md.


Part of Open Recruiter Tools — https://github.com/OpenRecruiterTools · Built by Dominic Gonsalves, founder of Formatix AI

About

Free PDF tools for recruiters that run entirely in your browser: redact a CV, merge, split, compress, watermark, header & footer. Nothing is uploaded.

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages