# GitHub Issues Monitor: New Issues by Label or Keyword (`accountable_eel/github-issues-monitor`) Actor

GitHub issues scraper and alerts: new or updated issues and pull requests in the repos you watch, filtered by label or keyword. One row per issue, only-new-since-last-run. Works without a token. $1.50 per 1,000 issues; a miss is free.

- **URL**: https://apify.com/accountable_eel/github-issues-monitor.md
- **Developed by:** [Adriana Voss](https://apify.com/accountable_eel) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 issue returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## GitHub Issues Monitor: New Issues by Label or Keyword

**GitHub issues scraper and alerts** for the repositories you already watch. List `owner/repo`, optionally narrow by label or keyword, and get one row per issue or pull request that was opened or updated in your window: title, state, labels, who opened it, comment count, dates, the first 500 characters of the text and the link. Tick "only new or updated since the last run" and a scheduled run returns, and bills, only what changed. No GitHub token is needed to start. You pay per issue returned; a quiet day costs only the start fee.

It reads GitHub's public REST API (`GET /repos/{owner}/{repo}/issues`), one request per repository. Your own token is optional and never stored.

### Who it's for

- **Maintainers and community managers** who want every new `good first issue` or `help wanted` in the repos they care about.
- **Open-source contributors and recruiters** watching a project for beginner-friendly or high-signal issues.
- **Dev-tool and support teams** who want an alert when a keyword (a feature, an error message, a competitor) shows up in an upstream repo's issues.
- **Agents and n8n/Make/Clay flows** that need GitHub issue alerts as structured rows.

### What you get

One dataset row per issue or pull request ("One row per issue" is on by default):

| Field | Meaning |
|---|---|
| `repo` | Canonical `owner/repo` |
| `number` | Issue or pull request number |
| `itemKind` | `issue` or `pull_request` |
| `title`, `state`, `labels` | As GitHub shows them |
| `author` | Public GitHub username that opened it |
| `authorAssociation` | Owner, member, contributor, first-timer, ... |
| `commentCount` | Comments so far |
| `createdAt`, `updatedAt`, `closedAt` | ISO timestamps; `closedAt` is null while open |
| `isDraft` | Pull requests only; null on issues |
| `bodyExcerpt` | First 500 characters of the text, or null |
| `issueUrl` | The GitHub page |

`query` and `scrapedAt` are on every row. With monitoring on, `isNew` and `firstSeenAt` say whether this issue (in its current updated state) is new to the watchlist. Missing values are `null`, never `0` or an empty string.

A repository that does not exist, is private, or has no issue matching your filters comes back as a `"found": false` row and is never charged. A monitoring run that finds nothing new is not charged either.

### Limits worth knowing

- **Rate limit.** Without a token GitHub allows about 60 requests per hour per IP, and Apify IPs are shared. A few repositories per run is fine; for a long watchlist or many runs, paste your own free token (5,000 requests/hour).
- **One page per repository.** The newest 100 updated issues are scanned, then your labels and keywords are applied. A busy repo with a short window is fine; a very busy repo with a long window sets `truncated` so you know to narrow it.
- **Labels are AND.** Listing two labels keeps only issues that carry both.

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `repos` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~github-issues-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"repos":["octocat/Hello-World"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

### Input

```json
{
  "repos": [
    "octocat/Hello-World"
  ]
}
```

One per line: owner/repo or a github.com URL. Public repositories only. Works without a token; paste your own free GitHub token below for 5,000 requests/hour instead of 60. Accepted formats: cli/cli, https://github.com/cli/cli.

Everything below `repos` is optional: `labels`, `includeKeywords`, `excludeKeywords`, `itemType` (issues, pull requests or both), `state`, `sinceDays` (default 7), `maxItems` per repository (default 30), `onlyNewSinceLastRun`, `deltaName` and your own `githubToken`.

### Output

One row per issue or pull request, for example:

| query | found | status | issueCount | truncated | issues | repo | number | itemKind | title | state | labels | author | authorAssociation | commentCount | createdAt | updatedAt | closedAt | isDraft | bodyExcerpt | issueUrl | isNew | firstSeenAt | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| octocat/Hello-World | true | OK | <issues returned> | <more were available> | \<all issues (full list)> | <repository> | <number> | <kind> | <title> | <state> | <labels> | <opened by> | \<author's role in the repo> | <comments> | <opened> | <last updated> | <closed> | <draft pull request> | \<description (first 500 characters)> | <issue page> | \<new or updated since the last run?> | <first seen on a run> | 1970-01-01T00:00:00.000Z |

A miss comes back as a row with `"found": false`, a `status` and a plain-English `message`, and is never charged.

### Example runs

Three inputs that need no credentials of any kind and return rows as they stand. Paste one into the Input tab and press Start.

**1. Everything updated this week in one repo**

```json
{
  "repos": ["octocat/Hello-World"],
  "state": "all",
  "maxItems": 10
}
```

**2. Open `good first issue` tickets across two repos**

```json
{
  "repos": ["cli/cli", "sindresorhus/got"],
  "labels": ["good first issue"],
  "state": "open",
  "sinceDays": 30
}
```

**3. GitHub issue alerts on a schedule: only new or updated bugs**

```json
{
  "repos": ["cli/cli"],
  "labels": ["bug"],
  "itemType": "issues",
  "onlyNewSinceLastRun": true,
  "sinceDays": 7
}
```

### Pricing

Pay-per-event. A flat per-run fee covers session/proxy warmup; you're billed
per item only when data is actually found and returned — see
`.actor/pay_per_event.json` for exact prices. A miss is never charged.

Charged once per issue or pull request row returned. A repository with nothing matching, a missing repository, or a monitoring run with nothing new is never charged.

### Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~github-issues-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"repos":["octocat/Hello-World"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~github-issues-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"repos":["octocat/Hello-World"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~github-issues-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"repos":["{{repository}}"]}`, mapping the row's repository into the `repos` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "github issues scraper" — the agent will find and run this actor.

### FAQ

**Do I need a GitHub token?** No. The default is GitHub's anonymous API (about 60 requests/hour per IP). Add your own free token only for long watchlists or frequent schedules.

**Does an updated issue come back again?** Yes, once per update. A new comment, label or state change moves `updatedAt`, and with monitoring on that counts as new. A run with no changes returns nothing and bills nothing.

**Can I get only issues, or only pull requests?** Yes: set "Issues, pull requests or both".

**Will a missing repository fail the run?** No. It is a `NOT_FOUND` row and is free.

# Actor input Schema

## `repos` (type: `array`):

One per line: owner/repo or a github.com URL. Public repositories only. Works without a token; paste your own free GitHub token below for 5,000 requests/hour instead of 60. Accepted formats: cli/cli, https://github.com/cli/cli. You're only charged for the ones we actually find — a miss costs nothing.

## `githubToken` (type: `string`):

Optional. Without a token GitHub allows about 60 requests/hour per IP, enough for a few repositories. Paste your own free personal access token (public-repo read is enough) for 5,000 requests/hour. The token is never written to the dataset or logs.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. One per line, case-insensitive. An issue is kept if its title, labels or first 500 characters of text contain at least one. Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Optional. One per line, case-insensitive. An issue is dropped if it contains any of these. Leave empty to skip nothing.

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

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `labels` (type: `array`):

Optional. One label per line, e.g. bug or good first issue. An issue is kept only if it carries every label listed. Leave empty for any label.

## `itemType` (type: `string`):

GitHub lists pull requests under issues. Pick what you want back.

## `state` (type: `string`):

Which issues to keep, by state.

## `sinceDays` (type: `integer`):

How far back to look, by last-updated time (a new comment or label counts as an update). Default 7, maximum 365. On a schedule, keep this at least as long as the gap between runs.

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

Newest-updated first. Default 30, maximum 100 (one GitHub page per repository).

## `onlyNewSinceLastRun` (type: `boolean`):

On: only issues and pull requests this watchlist has not already returned in their current state are returned and charged, so run it on a schedule as GitHub issue alerts. Off: every matching issue is returned every time. A quiet run costs only the start fee.

## `deltaName` (type: `string`):

Optional. Name this watchlist's memory so two schedules stay apart, or keep one memory across a filter change. Leave empty to auto-derive one from your filters.

## `columns` (type: `array`):

Choose which pieces of information to include in each result row. All are included by default.

## `expandRows` (type: `boolean`):

When on, each issue found gets its own row instead of being grouped under its repository. You're still only charged once per repository, no matter how many rows it produces.

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

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

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

Apify Proxy config. Residential recommended for anti-bot-sensitive targets.

## Actor input object example

```json
{
  "repos": [
    "octocat/Hello-World"
  ],
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "labels": [],
  "itemType": "both",
  "state": "all",
  "sinceDays": 7,
  "maxItems": 30,
  "onlyNewSinceLastRun": false,
  "deltaName": "",
  "columns": [
    "issueCount",
    "truncated",
    "issues",
    "repo",
    "number",
    "itemKind",
    "title",
    "state",
    "labels",
    "author",
    "authorAssociation",
    "commentCount",
    "createdAt",
    "updatedAt",
    "closedAt",
    "isDraft",
    "bodyExcerpt",
    "issueUrl",
    "isNew",
    "firstSeenAt"
  ],
  "expandRows": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "repos": [
        "octocat/Hello-World"
    ],
    "includeKeywords": [],
    "excludeKeywords": [],
    "labels": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/github-issues-monitor").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 = {
    "repos": ["octocat/Hello-World"],
    "includeKeywords": [],
    "excludeKeywords": [],
    "labels": [],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/github-issues-monitor").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 '{
  "repos": [
    "octocat/Hello-World"
  ],
  "includeKeywords": [],
  "excludeKeywords": [],
  "labels": []
}' |
apify call accountable_eel/github-issues-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,accountable_eel/github-issues-monitor"
        }
    }
}
```

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/4xoFJMsrPxRzYK0g1/builds/WCQn1KAaPS9AsRS5E/openapi.json
