# doda Jobs Scraper (Japan) (`superslowsloth/doda-jobs`) Actor

Scrape job listings from doda.jp, one of Japan's largest mid-career job boards: job id and URL, title, company, location, salary text with yen band where stated, employment type and feature tags - from the whole feed or any doda search URL.

- **URL**: https://apify.com/superslowsloth/doda-jobs.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** Jobs, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 job scrapeds

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

## doda Jobs Scraper (Japan)

Scrape job listings from [doda](https://doda.jp) - PERSOL CAREER's job board,
one of Japan's largest for mid-career hiring - and get one flat row per job:
id and URL, title, company, location, salary as printed (plus a yen band when
the card states one), employment type and feature tags. Japanese text is kept
exactly as doda prints it.

Run it on doda's whole job feed, or paste any search you built on doda.jp.

### Input

| field | meaning |
|---|---|
| `searchUrls` | Optional. doda search result URLs on `https://doda.jp/DodaFront/View/JobSearchList.action`, copied from your browser after setting conditions on the site. Every condition is kept; the actor manages the page number. Empty means doda's whole job feed |
| `maxItems` | Stop after this many jobs in total, shared across all search URLs. doda shows 50 jobs per page |
| `proxyConfiguration` | Apify datacenter proxy by default - see **Proxy** below |

### Output

| field | meaning |
|---|---|
| `job_id` | doda's numeric job id, from the `j_jid__<id>` part of the job URL (a string) |
| `url` | The job's detail page on doda.jp |
| `title` | The job headline printed under the company name |
| `company` | Company name as printed |
| `job_summary` | The card's 仕事 (work) row |
| `requirements` | The card's 対象 (who it is for) row |
| `location` | The card's 勤務地 (work location) row |
| `nearest_stations` | The card's 最寄駅 (nearest stations) row |
| `business` | The card's 事業 (company business) row |
| `salary_text` | The card's 給与 (salary) row as printed, lines joined with a newline |
| `salary_min_jpy`, `salary_max_jpy` | Yen, only when `salary_text` states exactly one band or floor - see below |
| `salary_period` | `year` for a 年収 band, `month` for a 月給 band, `null` when there is no band |
| `employment_types` | doda's employment-type badges, e.g. `["正社員"]`; a card can carry two (`["正社員", "契約社員"]`) |
| `tags` | Feature badges: 転勤なし, 上場企業, 職種未経験歓迎, 5名以上採用 ... |
| `is_new` | doda's "New" badge |
| `closing_soon` | doda's 締切間近 (closing soon) badge |
| `appeal` | The free-text pitch beside the card's photo |
| `image_url` | The card's photo |
| `search_url` | Which search produced this row (page number stripped) |

doda truncates long rows on the search page with "..."; this actor returns
them as printed and does not open each job's detail page.

#### Which fields can be `null`, and why `null` is not zero

- **`salary_min_jpy` / `salary_max_jpy` / `salary_period`** are `null` on most
  rows. On the 2026-10-01 feed most cards print example incomes
  ("年収570万円／入社5年目・主任", "モデル年収：503万円（30歳）") rather than a
  band, and an example is not a range. A value is filled only when the text
  states exactly one band or floor, such as "年収345万円～492万円" or
  "月給28万円以上". A floor has no maximum, so `salary_max_jpy` stays `null`.
  A card that gives two bands for two candidate profiles also gets `null`,
  because neither band belongs to the job as a whole. A `0` would read as
  "unpaid", and an invented band would read as a measurement.
- **`job_summary`, `requirements`, `location`, `nearest_stations`,
  `business`, `salary_text`** are `null` when the card has no row with that
  label. Most cards carry all six, but not every card does.
- **`image_url`** is `null` on doda's video cards. They show a video that a
  script loads, and the page links no image.
- **`appeal`** is `null` when the card has no pitch text.

There is **no posting-date column**. doda's search card shows no date of any
kind, and the "New" badge (`is_new`) is the only recency signal it gives.

### Scheduled maintenance: runs return no jobs during it

doda takes the whole site down for scheduled system maintenance. One window
was observed **early on Sunday morning JST**: on 2026-10-04 (a Sunday) every
doda URL, over every proxy exit tried, returned HTTP 503 with the notice
「現在システムメンテナンス中につき、dodaサイトはご利用いただけません」 and an
outage window of 01:00-06:00 JST.

If you run the actor during maintenance, it retries from fresh exits. It then
stops cleanly with **no jobs**, logs an error naming the scheduled maintenance
and the window doda states, and sets the run's status message to match. It
does not fail with a bare "HTTP 503". The actor-start event is still charged.
No job events are charged. Schedule recurring runs outside early Sunday JST.

### Proxy

The default is Apify's datacenter proxy. On 2026-10-01 doda answered a
datacenter exit with a full results page (HTTP 200). Residential exits are
not needed for this site and cost more.

### Billing

Pay per event: **$0.0014 per job** (`job-scraped`), plus a small
**actor-start** fee per run. Each job is charged once, after it has been
written to the dataset. The same job id is never charged twice in one run,
even when two of your searches both return it.

# Actor input Schema

## `searchUrls` (type: `array`):

Optional. doda search result URLs, copied from your browser after setting conditions on doda.jp - they must be on https://doda.jp/DodaFront/View/JobSearchList.action. Every condition in the URL is kept; the page number is managed by the actor. Leave empty to scrape doda's whole job feed, newest listings first as doda orders it. All URLs share the maxItems budget, in the order given.

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

Stop after this many jobs in total, shared across every search URL. doda shows 50 jobs per page, so every 50 jobs is one page request.

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

Apify datacenter proxy is the default: doda.jp answered a datacenter exit with a full results page (HTTP 200) on 2026-10-01. Residential is not needed and costs more.

## Actor input object example

```json
{
  "searchUrls": [
    "https://doda.jp/DodaFront/View/JobSearchList.action"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

No description

# 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 = {
    "searchUrls": [
        "https://doda.jp/DodaFront/View/JobSearchList.action"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/doda-jobs").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 = {
    "searchUrls": ["https://doda.jp/DodaFront/View/JobSearchList.action"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/doda-jobs").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 '{
  "searchUrls": [
    "https://doda.jp/DodaFront/View/JobSearchList.action"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call superslowsloth/doda-jobs --silent --output-dataset

```

## MCP server setup

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

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/SgYFc2X6pU2JurgIy/builds/Rwp6ZNneWdmAs1QWu/openapi.json
