# Startup Jobs Scraper: Salaries, Remote Jobs & Descriptions (`yugenox/startup-jobs-scraper`) Actor

Scrape startup jobs from startup.jobs by keyword, city radius, country or company. Filter by remote/hybrid, employment type, experience, salary in USD and posting date. Goes past the 500-results limit, with optional full descriptions and company websites. No login.

- **URL**: https://apify.com/yugenox/startup-jobs-scraper.md
- **Developed by:** [Yugenox Corp](https://apify.com/yugenox) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Startup Jobs Scraper (startup.jobs)

Collect job postings from **[startup.jobs](https://startup.jobs)**, a board with well over 100,000 open roles at startups. Search by keyword, city radius, state or country, and company. Filter the same way the site does: remote, hybrid or on-site, employment type, years of experience, posting date, and salary converted to US dollars. The output is a clean table, and you can add full job descriptions if you want them.

- **No login, no cookies.** Add keywords and filters, then press Start.
- **Goes past the 500-result limit.** The site stops a search at 500 results. This actor splits a big search into small time slices and pages through each one, so you can pull every matching job, including whole days or weeks of new postings.
- **Salary you can compare.** You get each salary in its original currency and interval, plus a US-dollar-per-year minimum and maximum you can sort and filter on.
- **Real locations.** A city is searched within a radius you choose. States, provinces and countries use their exact borders, so "Canada" means jobs located in Canada.
- **Full descriptions on request.** You can add the description as plain text and HTML, the closing date, the company website, which countries applicants may apply from, and the occupation category. Descriptions need Apify's unblocker proxy group on your plan; without it, jobs are saved without descriptions and descriptions are not charged.
- **Fast.** A few thousand jobs take well under a minute when descriptions are off.

### What you get

| Field | Example |
|---|---|
| `title` | Principal Software Engineer, Health Data & Interoperability (Remote) |
| `companyName`, `companyUrl`, `companyLogo` | Verto Health, https://startup.jobs/company/verto-health |
| `location`, `city`, `country`, `countryCode`, `latitude`, `longitude` | Toronto, Canada |
| `workplaceType` | Remote / Hybrid / On-site |
| `employmentType` | full-time, part-time, contractor, internship |
| `experienceYears` | 0-1, 1-3, 3-6, 6+ (when the post states it) |
| `salary` | CAD 165,000–190,000 / year |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryInterval` | 165000, 190000, CAD, year |
| `salaryMinUsd`, `salaryMaxUsd` | 118702, 136688 |
| `tags` | Developer, Engineer, Medical |
| `publishedAt`, `postedDaysAgo` | 2026-09-15T14:07:59Z, 9 |
| `url` | the job page on startup.jobs |
| `createdAt` | when the job was added to startup.jobs |
| `searchQuery`, `searchLocation` | which of your searches found the job |

With **Include full job descriptions** turned on, each job also gets `description` (plain text), `descriptionHtml`, `validThrough`, `companyWebsite`, `applicantLocationRequirements`, `jobLocationType`, `occupationalCategory`, `industry`, `employmentTypes`, `address` and `baseSalary`.

#### Sample row

```json
{
  "id": "10074188",
  "url": "https://startup.jobs/principal-software-engineer-health-data-interoperability-remote-verto-health-10074188",
  "title": "Principal Software Engineer, Health Data & Interoperability (Remote)",
  "companyName": "Verto Health",
  "companySlug": "verto-health",
  "companyId": 111747,
  "companyUrl": "https://startup.jobs/company/verto-health",
  "companyLogo": "https://startup.jobs/logos/111747",
  "location": "Toronto, Canada",
  "city": "Toronto",
  "country": "Canada",
  "countryCode": "CA",
  "latitude": 43.6548253,
  "longitude": -79.388447,
  "workplaceType": "Remote",
  "employmentType": "full-time",
  "experienceYears": "6+",
  "tags": ["Developer", "Engineer", "Medical"],
  "roleIds": [1, 2, 354],
  "hasSalary": true,
  "salary": "CAD 165,000–190,000 / year",
  "salaryMin": 165000,
  "salaryMax": 190000,
  "salaryCurrency": "CAD",
  "salaryInterval": "year",
  "salaryMinUsd": 118702,
  "salaryMaxUsd": 136688,
  "publishedAt": "2026-09-15T14:07:59Z",
  "postedDaysAgo": 9,
  "createdAt": "2026-09-15T14:04:48Z",
  "searchQuery": "software engineer",
  "searchLocation": "Canada",
  "description": "About the Company\n\nVerto Health is a health technology company ...",
  "validThrough": "2026-10-23T23:28:39Z",
  "companyWebsite": "https://verto.health/canada",
  "applicantLocationRequirements": ["Canada"],
  "jobLocationType": "TELECOMMUTE",
  "occupationalCategory": "15-1132.00 Software Developers, Application"
}
```

### How to use it

#### Newest remote engineering jobs this week

```json
{
  "queries": ["software engineer"],
  "workplaceType": ["remote"],
  "postedWithin": "7d",
  "maxItems": 200
}
```

#### Several roles in several places

Every keyword is combined with every location. Jobs found by more than one search are saved once.

```json
{
  "queries": ["product manager", "product designer"],
  "locations": ["Toronto", "London, UK", "Germany"],
  "radiusKm": 50,
  "maxItemsPerSearch": 100
}
```

#### Well-paid jobs with a salary shown

```json
{
  "queries": ["data engineer"],
  "locations": ["United States"],
  "hasSalary": true,
  "minSalaryUsd": 150000,
  "maxItems": 500
}
```

#### Every job at specific companies, with descriptions

```json
{
  "companies": ["Stripe", "https://startup.jobs/company/verto-health"],
  "includeDescription": true,
  "maxItems": 0
}
```

#### Every job posted in the last 24 hours (daily feed)

Leave the keywords empty and set `"postedWithin": "24h"` and `"maxItems": 0`. Schedule the run daily and you have a complete feed of new startup jobs.

### Input reference

| Input | What it does |
|---|---|
| **Search keywords** | Each keyword is a separate search. Leave it empty for all jobs that match your filters. |
| **Locations** | City (with radius), state or province, or country. "London, UK" picks the right London. "Remote" means remote jobs anywhere; "Remote, Canada" means remote jobs in Canada. |
| **Radius around a city** | 50 km by default. |
| **Workplace / Employment type / Experience** | Pick one or more values. Leave empty for all. |
| **Posted within** | Last 24 hours, 3, 7, 14 or 30 days. Through the API you can also pass a number of days, e.g. `"45"`. |
| **Only jobs that show a salary** | Skips posts without a salary range. |
| **Minimum / maximum salary (USD per year)** | Compares against each job's range converted to US dollars per year. |
| **Companies** | A company name, its startup.jobs slug, or its startup.jobs page URL. |
| **Role categories** | The site's categories, e.g. Engineer, Developer, Design, Marketing, Sales, Product Manager, Data Science, Machine Learning, Finance, Support. |
| **Max jobs** | Total cap across all searches, shared fairly between them first; searches with more results then fill any room left. 0 means everything that matches. |
| **Max jobs per search** | A cap for each keyword x location pair. |
| **Include full job descriptions** | Opens each job page. About 2 seconds per job, 10 at a time. Needs Apify's unblocker proxy group on your plan. |

### Use cases

- **Job seekers and career coaches:** a daily list of new remote or local startup roles that match a profile, with salary.
- **Recruiters and staffing agencies:** find startups that are hiring for the roles you place, with company website and location.
- **Sales and business development:** startups that are hiring engineers, designers or salespeople are growing and buying. Use the jobs as lead signals.
- **Salary research:** compare salary ranges by role, city, seniority and currency, normalised to USD.
- **Job boards and newsletters:** feed a niche board (AI, climate, fintech, remote) with fresh listings every day.
- **Labour-market analysis:** track hiring by role category, workplace type and country over time.

### FAQ

**How many jobs can I get?**
All of them. A single search on the site stops at 500 results. This actor keeps going by splitting the search into time slices, so a broad search can return tens of thousands of jobs. Use **Max jobs** to control the size of a run.

**Why do some jobs have no salary or experience level?**
Not every employer shares them. `hasSalary` tells you which jobs have a salary. The experience filter only matches jobs that state one, so it narrows results a lot.

**How does "Posted within" work?**
It uses the posting date shown on startup.jobs. Some employers only give a date, so their posts count from midnight UTC. `publishedAt` and `postedDaysAgo` are on every row.

**What order do results come in?**
Searches up to 500 jobs come back in the site's own ranking. Bigger searches come back newest first, one time slice at a time.

**Do I need a proxy?**
Apify's datacenter proxy, which every plan includes, is the default and is enough for search. If the datacenter IPs get rate limited, the actor switches to residential IPs by itself when your plan has them. Full descriptions are the exception: job pages only open through Apify's unblocker proxy group, which the actor picks for you.

**What if my Apify plan doesn't include the unblocker proxy?**
Search results work as usual. If you turn on **Include full job descriptions**, the actor checks your plan at the start of the run; without the unblocker group every job is still saved with all its search fields, `descriptionFetched` is `false`, descriptions are not charged, and the status message says what to enable in Apify Console → Proxy.

**What happens if startup.jobs is slow or down?**
The run still finishes normally. Every request is retried on fresh IPs with backoff, and the actor switches proxy type by itself when one keeps failing. If the site stays unreachable, the run ends with a clear status message and whatever it collected. You are never charged for jobs that were not saved to your dataset. If a run nears its time limit, it saves what it has and finishes with a "Partial" message instead of timing out.

**I copied my input from another job scraper. Will it work?**
Usually, yes. Common spellings such as `keywords`, `location`, `maxResults`, `limit`, `datePosted` and `jobType` are understood as well as the names above.

**What if a job page cannot be opened?**
The job is still saved with all its search fields, `descriptionFetched` is `false`, and there is no description charge for it.

**Can I run it on a schedule?**
Yes. Create a task with your input and schedule it daily. Add `"postedWithin": "24h"` to get only new jobs each time.

**Is there an API?**
Yes. Like every Apify actor, you can start it and read the results over the Apify API, or connect it to Make, Zapier, n8n, Google Sheets, Slack and more.

**Is it legal to scrape startup.jobs?**
This actor collects only public data: job postings that startup.jobs shows to every visitor without logging in, which employers publish so that people will see them. Full descriptions are written by employers and can sometimes include a recruiter's name or a contact email. If you store that kind of personal information, handle it under the privacy laws that apply to you, such as GDPR, PIPEDA or CCPA. Use the data in line with startup.jobs' terms of use, and check with a lawyer if you are unsure about your use case. For background, see Apify's guide [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

**Does it access any private data?**
No. It needs no account, login or cookies. It reads only what anyone can see on startup.jobs without signing in: the site's public job search and public job pages. It never sees applicant data, employer dashboards or anything else behind a login.

# Actor input Schema

## `queries` (type: `array`):

Job titles, skills or companies to search for, e.g. "product manager" or "react". Each keyword is its own search. Leave empty to get all jobs that match your filters.

## `locations` (type: `array`):

Cities (searched within the radius below), states/provinces or countries, e.g. "Toronto", "London, UK", "California", "Germany". Each location is combined with each keyword. Type "Remote" for remote jobs anywhere. Leave empty to search worldwide.

## `radiusKm` (type: `integer`):

How far around a city to look. States, provinces and countries always use their exact borders.

## `workplaceType` (type: `array`):

Only these workplace types. Leave empty for all.

## `employmentType` (type: `array`):

Only these employment types. Leave empty for all.

## `experience` (type: `array`):

Only jobs asking for this much experience. Many posts do not state it, so this filter narrows results a lot.

## `postedWithin` (type: `string`):

Only jobs posted this recently, using the posting date shown on the site. Some employers only give a date, so their posts count from midnight UTC.

## `hasSalary` (type: `boolean`):

Skip posts without a salary range.

## `minSalaryUsd` (type: `integer`):

Only jobs whose salary range reaches at least this much, converted to US dollars per year so every currency compares fairly.

## `maxSalaryUsd` (type: `integer`):

Only jobs whose salary range starts at or below this much (USD per year).

## `companies` (type: `array`):

Only jobs at these companies. Use the company name, its startup.jobs slug or its startup.jobs page URL, e.g. "Stripe" or "https://startup.jobs/company/stripe".

## `tags` (type: `array`):

Only jobs tagged with any of these categories, e.g. Engineer, Developer, Design, Marketing, Sales, Product Manager, Data Science, Machine Learning, Finance, Support, Ops, Recruiter, Senior, Junior, Internship.

## `maxItems` (type: `integer`):

Stop after this many jobs across all searches. With several searches the total is shared fairly first, then searches with more results fill any room left. 0 = everything that matches (this can be tens of thousands of jobs when no keyword or filter is set).

## `maxItemsPerSearch` (type: `integer`):

Cap for each keyword x location combination, so one broad search cannot use up the whole run. 0 = no cap.

## `includeDescription` (type: `boolean`):

Also open each job page for the full description (HTML and plain text), closing date, company website, which countries applicants may apply from, and the occupation category. Slower (about 2 seconds per job, 10 at a time) and charged as an extra event per job with a description. Needs Apify's UNBLOCKER proxy group: if your Apify plan doesn't include it, jobs are still saved but without descriptions, and descriptions are not charged.

## `descriptionConcurrency` (type: `integer`):

How many job pages to open in parallel when descriptions are on.

## `proxyConfiguration` (type: `object`):

Datacenter proxies are enough. The actor switches to residential IPs by itself if it needs to.

## `_noUnblocker` (type: `boolean`):

Internal (canaries): behave exactly like an account without the UNBLOCKER proxy group.

## `_noResidential` (type: `boolean`):

Internal (canaries): behave exactly like an account without the RESIDENTIAL proxy group.

## Actor input object example

```json
{
  "queries": [
    "software engineer",
    "product designer"
  ],
  "locations": [
    "Toronto",
    "London, UK",
    "Canada"
  ],
  "radiusKm": 50,
  "workplaceType": [
    "remote"
  ],
  "postedWithin": "7d",
  "hasSalary": false,
  "companies": [
    "Stripe",
    "https://startup.jobs/company/verto-health"
  ],
  "tags": [
    "Engineer",
    "Design"
  ],
  "maxItems": 50,
  "maxItemsPerSearch": 0,
  "includeDescription": false,
  "descriptionConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "_noUnblocker": false,
  "_noResidential": false
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped job postings.

## `run` (type: `string`):

Status and statistics for this run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "software engineer"
    ],
    "workplaceType": [
        "remote"
    ],
    "postedWithin": "7d",
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yugenox/startup-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "queries": ["software engineer"],
    "workplaceType": ["remote"],
    "postedWithin": "7d",
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("yugenox/startup-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "software engineer"
  ],
  "workplaceType": [
    "remote"
  ],
  "postedWithin": "7d",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call yugenox/startup-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yugenox/startup-jobs-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/rJ9S6FxeU7wgS8LfK/builds/SG4EoYCxnJLFxcTuM/openapi.json
