# jobs.ch Company Profiles With Coordinates (`gubidonius/jobsch-company-details`) Actor

Full employer profiles from jobs.ch: legal name, own website, street address, map coordinates, languages and how many adverts they are running. Tells a company with no adverts apart from a company whose count could not be read, because the site uses a different page title for each.

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

## Pricing

from $0.01 / 1,000 company returneds

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

## jobs.ch company profiles

Employer profiles from jobs.ch: name, legal name, own website, street address, postcode, town,
map coordinates, the languages the profile is published in, and how many adverts the company is
running.

Give it company profile URLs, or the bare path segment such as `86553-roomz-sa`. Feed it the
`companyProfileUrl` column from jobsch-jobs or the `profileUrl` column from jobsch-companies.

A bare id on its own does not work here, and that is a property of the source rather than a
limit of this Actor. A jobs.ch company needs its id and its name together to open. An advert is
the opposite, it opens on its id alone. So an entry like "86553" is reported back to you with
the reason instead of being turned into a URL that fails.

### A company that is gone does not say so

This is the part worth knowing before you trust any Swiss company scraper.

Ask jobs.ch for a company that does not exist and it answers HTTP 200 with its generic company
directory page, titled "Companies with open positions in the entire Switzerland". It does not
answer 404.

So the status code tells you nothing, and a loose parser can hand you the directory page's
content as if it were the company. This Actor recognises that page and puts the company in
`companiesGone` with the reason. A real 404 is handled too.

### Counting adverts, and knowing when you cannot

jobs.ch uses two page titles for a company profile. "Tellco Bank AG - 2 job offers on jobs.ch"
carries the number, one advert gets "1 job vacancy", and a company with no adverts gets
"Company profile from TradeXBank AG on jobs.ch" with no number at all.

So 0 means the page said none, and null means the wording changed and the number could not be
read. `advertCountKnown` tells you which. Watching an employer over time, a company that stopped
hiring reads 0, not null.

### The open adverts

Turn on the advert option and each company also gives you the adverts on the first page of its
own list.

That page carries no structured data, so those adverts have a title, place, workload and
contract type, and `datePosted` is null on every one. Use jobsch-job-details for the exact date.

Only the first page is read. Lonza Group reports 15 adverts and its first page serves 12, so
that row comes back with `openJobsComplete` false rather than looking complete and being short
by three. If the count could not be read at all, completeness is null rather than assumed.

For every advert of a large employer, use jobsch-jobs, which pages properly.

### Coordinates

`latitude` and `longitude` come from the profile. When a profile carries none they are null,
never 0. Zero would put a Swiss company in the Gulf of Guinea.

### Cost

Both events cost 0.00001 USD. One request per company, plus one more when you ask for the open
adverts. Reading those adverts costs no extra event. You are charged after rows are written, so
a company that is no longer listed costs nothing.

Duplicates in your own list are dropped before anything is fetched.

All measurements here are from 13 September 2026.

# Actor input Schema

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

Company profile URLs, or the bare path segment such as 86553-roomz-sa. Feed this the companyProfileUrl column from jobsch-jobs or the profileUrl column from jobsch-companies. A bare id WITHOUT the name does not open a profile on jobs.ch, so it is reported with the reason rather than guessed into a URL that would fail.

## `withOpenJobs` (type: `boolean`):

Adds one request per company and fills openJobs with the adverts on the first page of that company's own list. The list page carries no structured data, so these adverts have a title, place, workload and contract type but no exact posting date. Use jobsch-job-details for that. A company with more adverts than one page holds is marked openJobsComplete false rather than quietly cut.

## `maxJobsPerCompany` (type: `integer`):

How many adverts to keep per company when the option above is on. Only the first page of the company's list is read, so numbers above about 20 will not add rows.

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

How many companies to return at most, and the most you will be charged for. Duplicates in your own list are dropped before anything is fetched.

## Actor input object example

```json
{
  "companies": [
    "https://www.jobs.ch/en/companies/86553-roomz-sa/"
  ],
  "withOpenJobs": false,
  "maxJobsPerCompany": 20,
  "maxResults": 100
}
```

# 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 = {
    "companies": [
        "https://www.jobs.ch/en/companies/86553-roomz-sa/"
    ],
    "withOpenJobs": false,
    "maxJobsPerCompany": 20,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("gubidonius/jobsch-company-details").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 = {
    "companies": ["https://www.jobs.ch/en/companies/86553-roomz-sa/"],
    "withOpenJobs": False,
    "maxJobsPerCompany": 20,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("gubidonius/jobsch-company-details").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 '{
  "companies": [
    "https://www.jobs.ch/en/companies/86553-roomz-sa/"
  ],
  "withOpenJobs": false,
  "maxJobsPerCompany": 20,
  "maxResults": 100
}' |
apify call gubidonius/jobsch-company-details --silent --output-dataset

```

## MCP server setup

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

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/qN9sDSovL1W4YDH3g/builds/OH2H7DqeBPQ7jfxRs/openapi.json
