# GitHub Public Profile Phone Field Scraper (`w3crawler/github-public-phone-scraper`) Actor

Reads public GitHub user profile fields and returns an upstream phone field only if GitHub explicitly exposes one.

- **URL**: https://apify.com/w3crawler/github-public-phone-scraper.md
- **Developed by:** [w3crawler](https://apify.com/w3crawler) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 profile phones

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### What does GitHub Public Profile Phone Field Scraper do?

This Actor extracts **public GitHub profile fields** from the [GitHub REST user API](https://docs.github.com/en/rest/users/users#get-a-user) and the anonymous [GitHub profile page](https://github.com/). It reports a phone number only when GitHub explicitly exposes it as an upstream `phone` field, a `tel:` link, or clearly labeled public profile contact text. It never infers a number from a biography, location, username, company, repository, commit, or external link.

### Why use GitHub Public Profile Phone Field Scraper?

Use it for a small, auditable profile export, public contact-disclosure review, or scheduled monitoring of profiles you are authorized to analyze. Each row keeps the public source URLs, evidence type, bounded context, and a truthful negative observation when no supported phone disclosure is present. The Actor supports multiple usernames, case-insensitive deduplication, bounded concurrency, pacing, retries, run history, API access, scheduling, and Console monitoring. It does **not** use proxy rotation, login sessions, private endpoints, repository traversal, or external contact enrichment.

### What data can GitHub Public Profile Phone Field Scraper extract?

| Field                                        | Type             | Description                                            |
| -------------------------------------------- | ---------------- | ------------------------------------------------------ |
| `login`, `recordId`, `recordType`            | string           | Stable public profile identity and row discriminator.  |
| `profileUrl`, `sourceUrl`, `publicPageUrl`   | URL              | Public profile/API provenance.                         |
| `name`, `company`, `location`, `bio`, `blog` | string           | Public profile fields when GitHub returns them.        |
| `publicRepos`                                | integer          | Public repository count reported by GitHub.            |
| `phone`, `phoneFieldAvailable`               | string, boolean  | Explicit phone value and availability flag.            |
| `phoneDisclosure`, `phoneEvidence`           | string, array    | Evidence classification and per-number source/context. |
| `publicPageStatus`, `publicPageHttpStatus`   | string, integer  | Anonymous page coverage and HTTP status.               |
| `sourceFields`, `scrapedAt`                  | array, date-time | Observed surfaces and row timestamp.                   |

Diagnostics use `recordType: "diagnostic"`, `dataAvailable: false`, a stable `recordId`, source URL, bounded error, error code, and timestamp.

### How to scrape GitHub public profiles

1. Open the Actor in Apify Console and enter one `username` or a `usernames` list in the Input tab.
2. Set `maxItems` for the global number of deduplicated profiles, then choose concurrency and pacing appropriate for GitHub’s unauthenticated limits.
3. Start the run and inspect the dataset rows plus the `OUTPUT` run summary. Download or connect the dataset through the API, an integration, or a schedule.

### How much will it cost to scrape GitHub public profiles?

Apify charges according to the selected Actor pricing and the platform compute used by the run; this Actor does not promise a fixed price. Each profile makes up to two public requests (API and page), so more usernames, retries, concurrency, or long pacing increase run time and compute. Keep `maxItems` small for smoke tests and remember that unauthenticated GitHub responses can be rate-limited.

### Input

See the input tab for the complete configuration. `username` is one login and is combined before `usernames`; values are trimmed, validated against GitHub’s 1–39 character login rules, deduplicated case-insensitively, and then capped globally by `maxItems` (1–20, default 20). With no username, the safe default is `octocat`. `maxConcurrency` is 1–5 (default 2), and `delayMs` is 0–5000 (default 250). Unknown properties, non-integers, invalid logins, and out-of-range values are rejected.

#### Minimal/default run

```json
{}
```

#### Multiple profiles with deduplication

```json
{
  "username": "octocat",
  "usernames": ["OCTOCAT", "github", "torvalds"],
  "maxItems": 3,
  "maxConcurrency": 1,
  "delayMs": 250
}
```

#### Developer-controlled smoke run

```json
{
  "usernames": ["octocat", "github"],
  "maxItems": 2,
  "maxConcurrency": 2,
  "delayMs": 0
}
```

### Output

Normal profiles remain in the dataset even when no phone is exposed. `not_exposed_by_public_sources` means both supported public surfaces were checked without evidence; `not_exposed_by_public_api_and_page_unavailable` records that the API succeeded but the page could not be checked. A page failure does not discard a usable API profile. A request failure becomes a diagnostic row rather than fabricated profile data.

#### Normal negative observation

```json
{
  "recordType": "profile",
  "recordId": "github-public-phone:octocat",
  "dataAvailable": true,
  "accessStatus": "public",
  "extractionMethod": "github_rest_api_and_public_profile_page",
  "login": "octocat",
  "profileUrl": "https://github.com/octocat",
  "apiPhoneFieldPresent": false,
  "publicPageStatus": "checked",
  "phoneFieldAvailable": false,
  "phoneDisclosure": "not_exposed_by_public_sources",
  "sourceUrl": "https://api.github.com/users/octocat",
  "scrapedAt": "2026-09-08T00:00:00.000Z"
}
```

#### Explicit evidence and run summary

```json
{
  "recordType": "profile",
  "recordId": "github-public-phone:public-contact",
  "dataAvailable": true,
  "login": "public-contact",
  "phone": "+1 555 0100",
  "phoneFieldAvailable": true,
  "phoneDisclosure": "explicit_public_profile_contact_text",
  "phoneEvidence": [
    {
      "number": "+1 555 0100",
      "sourceUrl": "https://github.com/public-contact",
      "evidenceType": "explicit_public_profile_contact_text",
      "context": "Tel: +1 555 0100"
    }
  ]
}
```

`OUTPUT` records status, profile/diagnostic counts, evidence counts by source, API field presence, page coverage, and `completedAt`. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Tips and advanced options

Start with `maxItems: 1` and `delayMs: 0` for a smoke test, then increase gradually. A successful profile without a phone is expected and is not a scrape failure. Evidence is intentionally narrow: a number in a bio or a linked website is not accepted. Retry backoff is bounded, while the configured delay paces work across the input order. The Actor uses only public GitHub sources and does not accept a proxy configuration.

### FAQ, support, and responsible use

If a run has diagnostics, inspect `OUTPUT`, the diagnostic `errorCode`, and the source URL. GitHub profile markup and unauthenticated rate limits can change, so rerun with fewer profiles and more pacing when needed. Report bugs in the Actor’s Issues tab with the run ID, input, summary, and affected public URL. Use only data that profile owners chose to publish, follow GitHub’s terms and rate limits, respect privacy and applicable law, and obtain legal advice for personal-data processing. This Actor is not affiliated with or endorsed by GitHub.

# Actor input Schema

## `username` (type: `string`):

Public GitHub username, for example octocat.

## `usernames` (type: `array`):

Additional public GitHub usernames. Values are deduplicated case-insensitively.

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

Maximum number of deduplicated public profiles per run.

## `maxConcurrency` (type: `integer`):

Maximum concurrent unauthenticated GitHub requests.

## `delayMs` (type: `integer`):

Pacing delay between public API requests.

## Actor input object example

```json
{
  "username": "octocat",
  "maxItems": 20,
  "maxConcurrency": 2,
  "delayMs": 250
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `runSummary` (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 = {
    "username": "octocat",
    "delayMs": 250
};

// Run the Actor and wait for it to finish
const run = await client.actor("w3crawler/github-public-phone-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 = {
    "username": "octocat",
    "delayMs": 250,
}

# Run the Actor and wait for it to finish
run = client.actor("w3crawler/github-public-phone-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 '{
  "username": "octocat",
  "delayMs": 250
}' |
apify call w3crawler/github-public-phone-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,w3crawler/github-public-phone-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/Mi8hGnOuVNLRwrjjZ/builds/P3DC0n0b1xrxSlIve/openapi.json
