# How to Perform Multi-Market Job Searches Using linkedin-search and freehire-search

> Perform multi market job searches with MadsLorentzen/ai-job-search. Discover jobs on LinkedIn and Freehire using Bun CLI tools for global or regional targeting. Start your efficient job hunt now.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Both `linkedin-search` and `freehire-search` are zero-dependency Bun CLI tools that enable multi-market job discovery—LinkedIn via HTML scraping with textual location flags and Freehire via JSON API with geographic facets—allowing you to target multiple countries and regions from a single codebase.**

The `ai-job-search` repository by MadsLorentzen provides specialized command-line interfaces for automated job discovery across global markets. By combining these two tools, you can execute comprehensive multi-market job searches without external dependencies, API keys, or complex configuration files.

## Architecture of the Search Tools

Both tools share a uniform zero-dependency architecture built for the Bun runtime. According to [`SETUP.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SETUP.md) (lines 80-100), neither requires `npm install` beyond dev types; they run using only Bun's built-in `fetch` and string handling.

**`linkedin-search`** (located at [`.agents/skills/linkedin-search/cli/src/cli.ts`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/cli/src/cli.ts)) scrapes LinkedIn's public "jobs-guest" HTML endpoints and extracts job fields using regex helpers. It handles markets through free-text location strings.

**`freehire-search`** (located at [`.agents/skills/freehire-search/cli/src/cli.ts`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/freehire-search/cli/src/cli.ts)) queries the structured JSON API of freehire.me using facet-based geographic filters. The API returns normalized data, eliminating the need for HTML parsing.

## Configuring Market Parameters for LinkedIn Searches

LinkedIn searches accept market specifications through the **`--location`** (or `-l`) flag. As defined in [`.agents/skills/linkedin-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/SKILL.md) (lines 50-52), this flag receives a textual place string such as `"Berlin, Germany"` or `"Remote"`, which is sent directly to LinkedIn's guest endpoint.

To filter by workplace type, use the **`--remote`** flag (line 53). The CLI supports three output formats: `json` (default), `table`, and `plain`.

Example searches across different markets:

```bash

# Search for "data engineer" in Berlin, Germany

bun run .agents/skills/linkedin-search/cli/src/cli.ts \
    search -q "data engineer" -l "Berlin, Germany" --format table

# Same query for remote markets

bun run .agents/skills/linkedin-search/cli/src/cli.ts \
    search -q "data engineer" -l "Remote" --remote remote --format table

```

## Configuring Market Parameters for Freehire Searches

Freehire searches utilize structured **facet flags** to define markets without parsing ambiguity. According to [`.agents/skills/freehire-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/freehire-search/SKILL.md) (lines 88-99), you can target specific geographic levels using:

- **`--region`** (e.g., `eu`, `na`)
- **`--country`** (e.g., `US`, `DE`)
- **`--city`**

Additional filters include `--seniority`, `--category`, `--skill`, and `--remote` (lines 93-97). This facet approach allows you to target entire continents or specific municipalities with equal precision.

Example multi-market configurations:

```bash

# Senior backend roles in the EU region

bun run .agents/skills/freehire-search/cli/src/cli.ts \
    search -q "backend engineer" --seniority senior --region eu --format table

# Remote React jobs in the United States

bun run .agents/skills/freehire-search/cli/src/cli.ts \
    search -q "react" --remote remote --country US --format table

# DevOps positions in Germany posted in the last 14 days

bun run .agents/skills/freehire-search/cli/src/cli.ts \
    search --category devops --country DE --jobage 14 --format table

```

## Combining Tools for Comprehensive Multi-Market Coverage

To perform a true multi-market job search, combine both tools in a single script or Bash loop. Because `linkedin-search` accepts arbitrary location strings while `freehire-search` uses standardized facets, you can cover overlapping geographic regions using complementary approaches.

The following example searches LinkedIn across three specific cities while using Freehire to cover the entire EU region:

```bash
LOCATIONS=("Berlin, Germany" "London, United Kingdom" "Remote")
for loc in "${LOCATIONS[@]}"; do
  echo "=== LinkedIn results for $loc ==="
  bun run .agents/skills/linkedin-search/cli/src/cli.ts \
      search -q "machine learning" -l "$loc" --format table
done

echo "=== Freehire results for EU ==="
bun run .agents/skills/freehire-search/cli/src/cli.ts \
    search -q "machine learning" --region eu --format table

```

This approach leverages LinkedIn for granular city-level searches and Freehire for broad regional coverage, maximizing your multi-market job search reach.

## Workflow Integration and Automation

Both tools integrate automatically with the repository's `/scrape` workflow. The workflow discovers each skill under `.agents/skills/*/SKILL.md` and executes its `search` command when `enabled: true` is set, requiring no additional glue code.

**Important compliance note:** As documented in [`.agents/skills/linkedin-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/SKILL.md) (lines 29-33), automated bulk scraping violates LinkedIn's Terms of Service. Keep request volumes low and for personal use only. The Freehire service (lines 20-24) is publicly accessible, unauthenticated, and intended for personal use without API key requirements.

## Summary

- **Both tools** are zero-dependency Bun CLIs requiring no external libraries or API keys.
- **LinkedIn** uses free-text `--location` flags for market targeting, scraping HTML from public endpoints.
- **Freehire** uses structured facet flags (`--region`, `--country`, `--city`) to query a normalized JSON API.
- **Combine approaches** using Bash scripts to search specific cities via LinkedIn and broad regions via Freehire.
- **Integrate** with the `/scrape` workflow by enabling skills in their respective [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) files.
- **Respect TOS** by limiting LinkedIn scrape volumes to personal use only.

## Frequently Asked Questions

### Do I need API keys to use linkedin-search and freehire-search?

No. Neither tool requires API keys or authentication tokens. `linkedin-search` scrapes public LinkedIn HTML endpoints, while `freehire-search` queries the public freehire.me JSON API. Both use Bun's native `fetch` implementation without external dependencies.

### How do I search multiple countries simultaneously?

For LinkedIn, create a Bash loop iterating over location strings (e.g., `"Paris, France"`, `"Tokyo, Japan"`). For Freehire, use broad facet flags like `--region eu` to cover multiple countries in one query, or chain multiple `--country` flags if the CLI supports repeated arguments. The tools are designed to run sequentially in scripts for comprehensive coverage.

### What output formats are supported by both tools?

Both `linkedin-search` and `freehire-search` support three identical output formats: `json` (default), `table`, and `plain`. Specify your preferred format using the `--format` flag in any search command.

### Are these tools suitable for production or commercial use?

No. According to the source code in [`.agents/skills/linkedin-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/SKILL.md) (lines 29-33), automated scraping of LinkedIn violates their Terms of Service and should be limited to low-volume personal use. Freehire is also intended for personal use (lines 20-24). Neither tool should be deployed for commercial data harvesting or high-frequency automated job aggregation.