# Welcome to the Jungle Articles and Full Text (`gubidonius/wttj-articles`) Actor

Every article in the Welcome to the Jungle media archive with its full text, 8,584 across five language editions. The body is not in the site's search index and arrives in several blocks that must be joined. The publication date is a string that returns nothing to a date comparison.

- **URL**: https://apify.com/gubidonius/wttj-articles.md
- **Developed by:** [Gregory Bolshakov](https://apify.com/gubidonius) (community)
- **Categories:** News, Business, Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

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

## Welcome to the Jungle Articles and Full Text

The whole Welcome to the Jungle media archive with the article text, 8,584 articles across
five language editions. No key and no login.

### The body arrives in pieces

The article text is not in the site's search index. It comes from the article page, and it
arrives as a list of content blocks rather than one field.

Reading the first block and calling it the article is the mistake to avoid. On our test run 31
of 60 articles had more than one block, and taking only the first kept 43.8 percent of their
text. The worst one kept 19 percent. Nothing about that looks broken. The word count is just
smaller, and still believable.

This Actor joins every block, strips the HTML and reports `bodyBlockCount` so you can see how
many there were.

### Dates are not searchable at the source

`published_at` is a string in the index. Ask Algolia for `published_at > 0` and it answers
HTTP 200 with zero results and no error, which looks exactly like an archive with nothing in
it. So `publishedFrom` and `publishedTo` are applied here instead, against the date the search
already returns, and applied before the article page is fetched. An article outside your window
costs no request and is never charged. Our test run dropped 1,251 that way.

### What one row is

One article. The five language editions are written separately rather than translated, so an
English and a French piece on the same subject are two articles with two ids. 1,000 sampled
articles gave 1,000 ids, 1,000 references and 1,000 slugs.

`categories` is a list because an article is filed under several at once. 8,584 articles carry
10,433 category entries between them.

### Two fields worth knowing about

`contributors` is a newer field. It is on 213 of 400 records we sampled and on none of the 2019
and 2020 articles, so an empty list on an old article means the site records none.

`format` is only on the article page, so filtering on it means the page has to be read first.
That spends the row budget before the filter runs and your answer can come back short. It says
so in `limitedBy`, and you are not charged for rows it drops.

### What a run admits

Every row carries `searchTotalReported`, the count the site's own search gave for your filter,
in articles, the same unit as the rows. `RUN_SUMMARY` in the key-value store holds every cell
with what it reported and why it stopped, plus `complete`, `limitedBy`, `droppedByDateWindow`
and `droppedByFormatAfterReading`.

### Billing

Two events: a start fee charged only once articles are returned, and a per-article fee charged
after each one is written. Reading the full body costs no extra. A run that matches nothing
costs nothing.

# Actor input Schema

## `query` (type: `string`):

Words to look for in article titles, summaries and author names. Typo tolerant and ranked by relevance. Leave empty to walk the whole archive.

## `languages` (type: `array`):

Which language editions to read, as two-letter codes. The archive holds 8,584 articles: fr 4,814, en 1,601, cs 1,128, es 646 and sk 395, measured 9 September 2026. Each edition is written separately, so this is a real filter and not a translation setting.

## `categories` (type: `array`):

Categories as the site writes them in English, for example "Find a job", "Work trends", "Productivity & tools". There are 131 of them and an article is filed under several at once. Every value is checked against the live list, so a misspelling comes back with the real spelling.

## `authors` (type: `array`):

Author names exactly as the site writes them, for example "Laetitia Vitaud". 608 people have written for it, and the most prolific has 476 articles.

## `formats` (type: `array`):

Keep only these formats. The ones seen across 120 article pages on 9 September 2026 are advice, analysis, lists, interview, testimony, investigation, tribune and feature\_piece, and portrait and recap also occur. 9 of those 120 carried no format at all and are dropped by this filter. The format is only on the article page and not in the search index, so it can only be applied after the page is read. That means the row budget is spent before this filter runs and your answer can come back short. It is reported in limitedBy when that happens, and you are never charged for a row this drops.

## `publishedFrom` (type: `string`):

Earliest publication date, as YYYY-MM-DD. Applied here rather than in the search, because the date is a string in the index and a date comparison against it returns zero results with no error. It is applied before the article page is read, so a filtered article costs nothing.

## `publishedTo` (type: `string`):

Latest publication date, as YYYY-MM-DD. The whole of that day is included.

## `fullText` (type: `boolean`):

On by default. Reads each article page for the body, the lead, the format and the last update date, one request per article. The body is not in the search index at all. Articles average about 12,400 characters, and one in ten is split across several blocks that are joined back together.

## `language` (type: `string`):

The language for category names, which the site holds in five languages at once. This does not change which articles you get, only how their categories are labelled.

## `maxResults` (type: `integer`):

The most articles to return, and what you are charged for.

## Actor input object example

```json
{
  "query": "remote work",
  "languages": [
    "en"
  ],
  "categories": [],
  "authors": [],
  "formats": [],
  "publishedFrom": "",
  "publishedTo": "",
  "fullText": true,
  "language": "en",
  "maxResults": 50
}
```

# Actor output Schema

## `results` (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 = {
    "query": "remote work",
    "languages": [
        "en"
    ],
    "categories": [],
    "authors": [],
    "formats": [],
    "publishedFrom": "",
    "publishedTo": "",
    "fullText": true,
    "language": "en",
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("gubidonius/wttj-articles").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 = {
    "query": "remote work",
    "languages": ["en"],
    "categories": [],
    "authors": [],
    "formats": [],
    "publishedFrom": "",
    "publishedTo": "",
    "fullText": True,
    "language": "en",
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("gubidonius/wttj-articles").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 '{
  "query": "remote work",
  "languages": [
    "en"
  ],
  "categories": [],
  "authors": [],
  "formats": [],
  "publishedFrom": "",
  "publishedTo": "",
  "fullText": true,
  "language": "en",
  "maxResults": 50
}' |
apify call gubidonius/wttj-articles --silent --output-dataset

```

## MCP server setup

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

```

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/ZIQE2r827v3P3bejA/builds/ipq5WCYILmcYGGzoT/openapi.json
