GitHub Discussions Scraper avatar

GitHub Discussions Scraper

Pricing

from $0.05 / 1,000 discussions

Go to Apify Store
GitHub Discussions Scraper

GitHub Discussions Scraper

Collect public GitHub organization, repository, and individual discussions. Save one row per discussion with text, authors, categories, activity times, comments, replies, reactions, and source links.

Pricing

from $0.05 / 1,000 discussions

Rating

0.0

(0)

Developer

Maxime Dupré

Maxime Dupré

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

💬 Turn GitHub Discussions into usable data

Support teams, developer advocates, and product researchers can collect public GitHub Discussions in a structured dataset. Each saved row includes the discussion text, repository context, author, activity times, comments, and source links. It also includes categories, labels, reactions, and replies when GitHub exposes them. Use the data to review community questions, track product feedback, and build a searchable support or research workflow.

Use cases

📦 One row for each public discussion

Returned data

The Actor saves one normalized dataset row for each eligible public GitHub discussion. Every row keeps a stable discussionId, the canonical discussionUrl, and the submitted sourceUrl. Text is available as body, with rendered HTML in bodyHtml. Public author, repository, date, answer, category, label, reaction, comment, and reply data follow the output schema when GitHub exposes them.

🔎 Find public GitHub discussions

How it works

Choose one target for each run: organization discussions, repository discussions, or individual discussion URLs. Add one or more public URLs in that target's field. The Actor reads public GitHub discussion pages and saves one row for each eligible discussion. Category, latest activity, and order settings apply to organization and repository discovery. A direct discussion URL is useful when you need one known page.

Start with one URL and a small maxItems value to check the source. Use category or latestActivityAfter to narrow an index run. Leave maxItems empty to return all available results until the source is exhausted. Use discussionId and discussionUrl to join data across runs, and keep sourceUrl to trace each row to its submitted URL.

⚙️ Input

Choose one target for each run. Add URLs only in its matching list. URLs in other target sections are ignored. category, latestActivityAfter, and sortOrder apply only to organization and repository discovery. maxItems limits the discussions saved. Leave it empty to return all available results until the source is exhausted.

Input fields

FieldTypeWhat it does
targetSelectChooses Organization discussions, Repository discussions, or Individual discussion URLs for this run.
organizationUrlsURL listAdds public GitHub organization discussion index URLs when target is organization.
organizationUrls[].urlURLA public HTTPS URL for an organization's GitHub Discussions index.
repositoryUrlsURL listAdds public GitHub repository discussion index URLs when target is repository.
repositoryUrls[].urlURLA public HTTPS URL for a repository's GitHub Discussions index.
discussionUrlsURL listAdds public GitHub discussion URLs when target is discussion.
discussionUrls[].urlURLA public HTTPS URL for one GitHub discussion.
categoryStringKeeps one GitHub Discussions category during organization or repository discovery. Leave it empty to include all categories.
latestActivityAfterUTC date stringKeeps discussions whose latest activity is on or after this date during organization or repository discovery. Leave it empty to include all dates.
sortOrderSelectOrders organization and repository lists by latest activity, top, newest, or oldest.
maxItemsIntegerStops after this many discussions. Leave it empty to return all available results until the source is exhausted.

Example input

This input came from a successful run:

{
"target": "discussion",
"discussionUrls": [
{
"url": "https://github.com/orgs/community/discussions/184710"
}
],
"sortOrder": "latest",
"maxItems": 20
}

🧾 Output

Dataset output

The dataset output links to the Apify dataset overview. Each dataset row uses the same discussion shape for organization, repository, and direct discussion URLs. isAnswered and category appear when GitHub exposes them. Arrays such as labels, reactions, and comments can be empty.

Run output

FieldTypeWhat it does
datasetURLLinks to the dataset with one row for each public GitHub discussion.

Discussion row fields

FieldTypeWhat it does
discussionIdStringStable ID for the discussion.
discussionUrlURLCanonical public URL for the discussion.
sourceUrlURLSubmitted URL that led to this discussion row.
titleStringDiscussion title.
bodyStringPlain text body of the discussion.
bodyHtmlHTML stringRendered HTML body of the discussion.
ownerStringGitHub user or organization that owns the repository.
repositoryObjectRepository that contains the discussion.
repository.nameStringShort repository name.
repository.fullNameStringRepository name with its owner.
repository.urlURLPublic URL for the repository.
numberIntegerDiscussion number in its repository.
authorObjectPublic author of the discussion.
author.loginStringGitHub login of the discussion author.
author.profileUrlURLPublic profile URL for the discussion author, when available.
createdAtDate-time stringTime when the discussion was created.
lastActivityAtDate-time stringTime of the latest public activity.
isAnsweredBooleanWhether GitHub marks the discussion answered, when publicly exposed.
categoryStringDiscussion category, when publicly exposed.
labelsString arrayLabels assigned to the discussion.
reactionsObject arrayReaction counts shown on the discussion.
reactions[].typeStringReaction type name.
reactions[].countIntegerNumber of reactions of that type.
commentCountIntegerNumber of publicly rendered comments.
commentsObject arrayPublic comments and their nested replies.
comments[].urlURLPublic URL for the comment.
comments[].authorObjectPublic author of the comment.
comments[].author.loginStringGitHub login of the comment author.
comments[].author.profileUrlURLPublic profile URL for the comment author, when available.
comments[].bodyStringPlain text body of the comment, when available.
comments[].bodyHtmlHTML stringRendered HTML body of the comment, when available.
comments[].createdAtDate-time stringTime when the comment was created.
comments[].repliesObject arrayReplies nested under the comment.
comments[].replies[].urlURLPublic URL for a reply.
comments[].replies[].authorObjectPublic author of the reply.
comments[].replies[].author.loginStringGitHub login of the reply author.
comments[].replies[].author.profileUrlURLPublic profile URL for the reply author, when available.
comments[].replies[].bodyStringPlain text body of the reply, when available.
comments[].replies[].bodyHtmlHTML stringRendered HTML body of the reply, when available.
comments[].replies[].createdAtDate-time stringTime when the reply was created.
comments[].replies[].repliesObject arrayFurther nested replies with the same comment fields.

Example discussion row

This is a complete row from a successful current-beta repository run.

{
"discussionId": "nodejs/nodejs.org#7145",
"discussionUrl": "https://github.com/nodejs/nodejs.org/discussions/7145",
"sourceUrl": "https://github.com/nodejs/nodejs.org/discussions",
"title": "change name of next.something and next-data",
"body": "I don't think these names are 100% right. Because 95% of them are server side code, but not specific to nextjs. For example, it could be integrated with remix or fatsify. So I think we could review the appointment of the rosters and the structure they are in.",
"bodyHtml": "<p dir=\"auto\">I don&apos;t think these names are 100% right.</p> <p dir=\"auto\">Because 95% of them are server side code, but not specific to nextjs. For example, it could be integrated with remix or fatsify.</p> <p dir=\"auto\">So I think we could review the appointment of the rosters and the structure they are in.</p>",
"owner": "nodejs",
"repository": {
"name": "nodejs.org",
"fullName": "nodejs/nodejs.org",
"url": "https://github.com/nodejs/nodejs.org"
},
"number": 7145,
"author": {
"login": "AugustinMauroy",
"profileUrl": "https://github.com/AugustinMauroy"
},
"createdAt": "2024-10-26T09:47:18Z",
"lastActivityAt": "2025-08-22T00:00:59.000Z",
"category": "Ideas",
"labels": [],
"reactions": [
{
"type": "heart",
"count": 2
}
],
"commentCount": 2,
"comments": [
{
"url": "https://github.com/nodejs/nodejs.org/discussions/7145#discussioncomment-11328103",
"author": {
"login": "ovflowd",
"profileUrl": "https://github.com/ovflowd"
},
"body": "I'm +1 renaming these. We could call them engine.XXX (for next.XXX) and server-data for (next-data)",
"bodyHtml": "<p dir=\"auto\">I&apos;m +1 renaming these.</p> <p dir=\"auto\">We could call them <code class=\"notranslate\">engine.XXX</code> (for <code class=\"notranslate\">next.XXX</code>) and <code class=\"notranslate\">server-data</code> for (<code class=\"notranslate\">next-data</code>)</p>",
"createdAt": "2024-11-20T19:50:48Z",
"replies": [
{
"url": "https://github.com/nodejs/nodejs.org/discussions/7145#discussioncomment-11328666",
"author": {
"login": "AugustinMauroy",
"profileUrl": "https://github.com/AugustinMauroy"
},
"body": "What's done quite a bit too, but that's up to the devs, is to put all that in a lib directory, for example, which is what next.js offers for setting up prisma.",
"bodyHtml": "<p dir=\"auto\">What&apos;s done quite a bit too, but that&apos;s up to the devs, is to put all that in a <code class=\"notranslate\">lib</code> directory, for example, which is what next.js offers for setting up prisma.</p>",
"createdAt": "2024-11-20T21:03:24Z",
"replies": []
}
]
}
]
}

💳 Pricing

Pay per saved discussion

This Actor uses pay-per-event pricing. The primary event is charged once for each public discussion saved to the dataset. The active per-discussion price is shown in Apify Console. Use maxItems and the discovery filters to control how many discussions you ask for.

🔌 Integrations

Use the dataset in your workflow

Open the dataset output after a run, or use the Apify API to read the structured discussion rows in your workflow.

❓ FAQ

Can I use an organization, repository, or direct discussion URL?

Yes. Choose the matching target and add one or more public GitHub URLs. Organization and repository targets use discussion index URLs. The discussion target uses individual discussion URLs.

Does this collect GitHub issues or GitLab discussions?

No. This Actor collects public GitHub Discussions. It does not collect GitHub issues or GitLab discussions.

Can I mix target types in one run?

No. Choose one target for each run. URLs in the other target sections are ignored.

Do I need a GitHub login or token?

No. The Actor is for public GitHub discussion pages that can be viewed without a customer login.

Which filters work with index URLs?

category, latestActivityAfter, and sortOrder apply to organization and repository discovery. A category keeps one category, a date keeps discussions with activity on or after that date, and order chooses latest activity, top, newest, or oldest.

What does leaving maxItems empty do?

It returns all available results until the source is exhausted. Use a number when you want to stop after a set number of discussions.

Are comments and replies included?

The output includes comments and nested reply fields. Comments, replies, and their public author data appear when GitHub renders them on the discussion page.

What if a discussion has no comments or reactions?

The row still includes the discussion fields, and the related arrays can be empty. Optional public fields such as category or isAnswered appear when GitHub exposes them.

How do I connect rows from different runs?

Use the stable discussionId or canonical discussionUrl as the discussion key. Keep sourceUrl when you also need to know which submitted URL led to the row.

📝 Changelog

0.0: Initial release

🆘 Support

For issues, questions, or feature requests, file a ticket and I'll fix or implement it in less than 24h 🫡

Made with ❤️ by Maxime Dupré