# JobKorea Jobs Scraper (Korea) (`signaldatatools/jobkorea-jobs-scraper`) Actor

Scrape full-time job postings from JobKorea, Korea's largest job board: titles, hiring companies, required experience and education, employment type, work location, advertised pay and application deadlines.

- **URL**: https://apify.com/signaldatatools/jobkorea-jobs-scraper.md
- **Developed by:** [Signal Data Tools](https://apify.com/signaldatatools) (community)
- **Categories:** Jobs, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## JobKorea Jobs Scraper (Korea)

Pull structured job-posting data from **JobKorea** (jobkorea.co.kr), Korea's largest
full-time recruitment board. Point it at a region and a job category and it returns the
ranked posting list with company name, required experience and education, employment
type, location, deadline and the skill tags each employer attached — the fields Korean
candidates actually filter on.

The Korean hiring market is almost invisible from outside Korea. There is no public API,
the postings are Korean-language, and most of the big portals block automated access.
JobKorea's `robots.txt` is the exception: it **explicitly allows** the public job list at
`/recruit/joblist` and the posting permalink at `/Recruit/GI_Read`. This Actor stays
strictly inside that allowance.

Verified on a live run: **60 postings in 5 seconds**, and a deeper run of **400 unique
postings across 4 pages in 5.8 seconds**. No blocking encountered.

### What you get

One dataset row per job posting:

| Field | Type | Description |
|---|---|---|
| `jobId` | string | JobKorea posting number |
| `title` | string | Job title exactly as posted |
| `url` | string | Canonical posting URL (`/Recruit/GI_Read/…`) |
| `companyName` | string | Hiring company as listed |
| `companyUrl` | string | Company profile page URL |
| `experienceLevel` | string | Career requirement (e.g. `경력무관`, `경력 3년↑`) |
| `educationLevel` | string | Education requirement (e.g. `고졸↑`, `대졸↑`) |
| `employmentType` | string | Contract type (e.g. `정규직`, `계약직`) |
| `location` | string | Work location as displayed |
| `salaryText` | string | Pay text where the employer discloses one, otherwise `null` |
| `deadline` | string | Application deadline as displayed |
| `postedDate` | string | Relative posting age (e.g. `2일 전 등록`) |
| `tags` | array | Skill / duty keywords attached to the posting |
| `rank` | integer | Position within the result list |
| `scrapedAt` | string | ISO-8601 UTC timestamp |

### Input

```json
{
  "regionCodes": ["I000", "B000"],
  "dutyCategoryCodes": ["10031"],
  "maxItems": 400,
  "maxPages": 4,
  "pageSize": 100,
  "requestDelaySeconds": 2,
  "respectRobotsTxt": true,
  "includeContactInfo": false,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyCountry": "KR" }
}
```

| Option | Default | Notes |
|---|---|---|
| `regionCodes` | `[]` (whole country) | 16 region codes; comma-separated multi-region verified |
| `dutyCategoryCodes` | `[]` (all categories) | 14 duty codes, `10026`–`10039` |
| `maxItems` | 100 | Hard stop across the whole run (max 5000) |
| `maxPages` | 3 | Listing pages to walk (max 100) |
| `pageSize` | 40 | Site default is 40; `100` is the highest verified value |
| `requestDelaySeconds` | 2 | Politeness pause between requests |
| `respectRobotsTxt` | `true` | Re-checks robots.txt at runtime, skips disallowed URLs |
| `includeContactInfo` | `false` | Off by default; keeps personal contact data out of your dataset |
| `proxyConfiguration` | Apify Proxy, KR | A Korean IP gives the most consistent results |

**Region codes:** `I000` Seoul, `B000` Gyeonggi, `K000` Incheon, `G000` Daejeon,
`1000` Sejong, `O000` Chungnam, `P000` Chungbuk, `L000` Gwangju/Jeonnam, `M000` Jeonbuk,
`F000` Daegu, `D000` Gyeongbuk, `H000` Busan, `J000` Ulsan, `C000` Gyeongnam,
`A000` Gangwon, `N000` Jeju.

**Duty category codes:** `10026` Planning/Strategy, `10027` Legal/Admin, `10028` HR,
`10029` Accounting/Tax, `10030` Marketing/Ads/MD, `10031` AI/Development/Data,
`10032` Design, `10033` Logistics/Trade, `10034` Driving/Delivery, `10035` Sales,
`10036` Customer support/TM, `10037` Finance/Insurance, `10038` Food & beverage,
`10039` Customer service/Retail.

### Sample output

```json
{
  "jobId": "49970052",
  "title": "[Coach Korea] 리테일 매장 판매직 정규직 채용",
  "url": "https://www.jobkorea.co.kr/Recruit/GI_Read/49970052",
  "companyName": "코우치코리아리미티드 유한회사",
  "companyUrl": "https://www.jobkorea.co.kr/Recruit/Co_Read/C/25351341",
  "experienceLevel": "경력무관",
  "educationLevel": "고졸↑",
  "location": "서울 강남구 외",
  "employmentType": "정규직 외",
  "salaryText": null,
  "deadline": "~10/11(일)",
  "postedDate": "2일 전 등록",
  "tags": ["거래처관리", "고객관리", "의류판매", "캐셔"],
  "rank": 1,
  "scrapedAt": "2026-09-13T09:00:51Z"
}
```

### Typical uses

- **Recruitment market intelligence** — measure hiring volume by region, sector and seniority
- **Skills and salary demand tracking** — trend the tag cloud and disclosed pay over time
- **Competitor hiring monitoring** — watch which roles a named company is opening and closing
- **HR-tech data feeds** — keep a job-aggregator or ATS enrichment pipeline stocked with Korean postings

### Responsible use

- Reads **public job listings only**. JobKorea's `robots.txt` explicitly allows
  `/recruit/joblist` and `/Recruit/GI_Read`; the Actor opens the allowed listing page
  once and then pages it with the listing page's own pager call. It never builds a URL
  on `/Search?TS_Search=` or `/Search/?stext=`, which `robots.txt` disallows.
- `respectRobotsTxt` is on by default and enforced before every single request.
- Requests are paced (default 2s) with retries on transient failures.
- **Personal data is excluded by default.** With `includeContactInfo: false`, phone and
  e-mail fields are dropped and any phone/e-mail pattern inside text fields is replaced
  with `[removed]`.
- Job titles, company names and posting text belong to their respective owners. You are
  responsible for how you use the output, including compliance with employment and data
  protection law in your jurisdiction.

### Pricing

Pay per result. You are charged only for rows actually delivered to your dataset.

***

### 한국어 요약

**잡코리아 채용공고 크롤러.** 지역과 직무를 고르면 잡코리아 공고 목록을 그대로 표로
뽑아 줍니다. 공고 제목·회사명·경력조건·학력조건·고용형태·근무지·마감일·등록일·직무
태그가 한 줄씩 나옵니다. 한 페이지 40개가 기본이고 최대 100개까지 늘릴 수 있습니다.

- **지역 선택**: 서울·경기·인천 등 16개 코드, 여러 지역 동시 지정 실측 확인
- **직무 선택**: 기획·인사·개발/데이터·디자인·영업 등 14개 직무 코드
- **속도**: 60건 5초, 4페이지 400건 5.8초 실측(차단 없음)
- **안전장치**: robots.txt 준수가 기본값(켜짐), 요청 간 2초 지연
- **개인정보**: 기본적으로 전화번호·이메일은 수집하지 않고, 본문에 섞여 있어도 `[removed]` 로 지웁니다
- 잡코리아 robots.txt가 **허용**한 `/recruit/joblist`·`/Recruit/GI_Read` 만 읽고,
  막아둔 `/Search?TS_Search=` 검색 경로는 아예 건드리지 않습니다

**요금**: 결과 1건당 과금(pay-per-result). 실제로 받은 줄 수만큼만 냅니다.

# Actor input Schema

## `regionCodes` (type: `array`):

JobKorea region codes to filter by. Leave empty for the whole country. Codes: I000 Seoul, B000 Gyeonggi, K000 Incheon, G000 Daejeon, 1000 Sejong, O000 Chungnam, P000 Chungbuk, L000 Gwangju/Jeonnam, M000 Jeonbuk, F000 Daegu, D000 Gyeongbuk, H000 Busan, J000 Ulsan, C000 Gyeongnam, A000 Gangwon, N000 Jeju.

## `dutyCategoryCodes` (type: `array`):

JobKorea duty-category codes. Leave empty for all categories. Codes: 10026 Planning/Strategy, 10027 Legal/Admin, 10028 HR, 10029 Accounting/Tax, 10030 Marketing/Ads/MD, 10031 AI/Development/Data, 10032 Design, 10033 Logistics/Trade, 10034 Driving/Delivery, 10035 Sales, 10036 Customer support/TM, 10037 Finance/Insurance, 10038 Food & beverage, 10039 Customer service/Retail.

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

Stop after this many job postings in total.

## `maxPages` (type: `integer`):

Listing pages to walk. Combined with the page size this caps how deep the actor goes.

## `pageSize` (type: `integer`):

How many postings to request per page. 40 is the site default; 100 is the highest value that was verified to work.

## `requestDelaySeconds` (type: `integer`):

Politeness pause between HTTP requests.

## `respectRobotsTxt` (type: `boolean`):

Check the target's robots.txt before every request and skip disallowed URLs.

## `includeContactInfo` (type: `boolean`):

Off by default. When off, phone numbers and e-mail addresses are stripped from the output.

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

Apify Proxy settings. A Korean residential or datacenter IP is recommended.

## Actor input object example

```json
{
  "regionCodes": [
    "I000"
  ],
  "dutyCategoryCodes": [],
  "maxItems": 100,
  "maxPages": 3,
  "pageSize": 40,
  "requestDelaySeconds": 2,
  "respectRobotsTxt": true,
  "includeContactInfo": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyCountry": "KR"
  }
}
```

# Actor output Schema

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

Job postings scraped in this run, as a dataset (JSON/CSV/Excel via the Apify API).

## `datasetView` (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 = {
    "regionCodes": [
        "I000"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("signaldatatools/jobkorea-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 = { "regionCodes": ["I000"] }

# Run the Actor and wait for it to finish
run = client.actor("signaldatatools/jobkorea-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 '{
  "regionCodes": [
    "I000"
  ]
}' |
apify call signaldatatools/jobkorea-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,signaldatatools/jobkorea-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/nWOj1fVnlebDVngEN/builds/TvkHcAoBDcp8ufpGU/openapi.json
