Skip to content

fix(apify): include live streams in YouTube profile scrapes#754

Merged
sweetmantech merged 2 commits into
mainfrom
feat/youtube-scrape-streams
Jul 5, 2026
Merged

fix(apify): include live streams in YouTube profile scrapes#754
sweetmantech merged 2 commits into
mainfrom
feat/youtube-scrape-streams

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Why

POST /api/socials/{id}/scrape?posts=N on a YouTube profile returns up to N videos + N Shorts but zero live streams (verified live on @mycowtf: 50-item dataset = 25 videos + 25 shorts, 0 streams, while the channel's Streams tab has 27). The streamers/youtube-scraper actor takes three per-tab depth knobs; posts was forwarded to maxResults (Videos) and maxResultsShorts (Shorts), but maxResultStreams stayed hardcoded to 0 in DEFAULT_INPUT — so the Streams tab was never scraped.

What

Forward posts to maxResultStreams exactly like the other two knobs (one line in startYoutubeProfileScraping.ts). The legacy profile snapshot (posts omitted) still excludes streams, matching current behavior.

TDD: test updated first (red — maxResultStreams: 20 unmet, stayed 0), then the fix (green). Full suite: 705 files / 3893 tests pass.

Downstream is already stream-safe: the webhook handler only persists the channel profile from items[0], and GET /api/apify/runs/{runId} returns raw dataset items untouched.

Pricing note (no change needed)

getSocialScrapeCreditCost was margin-checked against a 2×posts YouTube worst case (chat#1836); streams make it 3×posts, dropping worst-case margin at posts=100 from ~1.75× to ~1.17× — still profitable, keeping the flat 5 + posts rule (confirmed with @sweetmantech).

Verify

  • Post-deploy: POST /api/socials/{id}/scrape?posts=25 on a channel with streams → dataset includes Streams-tab items (also confirms the isLive: false default input is a search-mode filter that doesn't suppress channel-scrape stream items)

🤖 Generated with Claude Code


Summary by cubic

Include live streams in YouTube profile scrapes by forwarding the posts parameter to maxResultStreams, so requests now return videos, Shorts, and streams when posts is set. When posts is omitted, the legacy snapshot remains (Shorts and streams excluded).

  • Bug Fixes
    • Pass posts to maxResultStreams in startYoutubeProfileScraping.ts (aligned with maxResults and maxResultsShorts); removed an outdated inline legacy note.
    • Updated tests to confirm streams are included with posts and excluded without it for streamers/youtube-scraper.

Written for commit 3e6e886. Summary will update on new commits.

Review in cubic

The streamers/youtube-scraper actor takes three per-tab depth knobs;
posts was forwarded to maxResults (Videos) and maxResultsShorts
(Shorts) but maxResultStreams stayed hardcoded to 0, so the Streams
tab never appeared in scrape datasets. Forward posts to it like the
other two. Legacy snapshot (posts omitted) still excludes them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 5, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
api Ready Ready Preview Jul 5, 2026 8:38pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@sweetmantech, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 11 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 31007c14-e65d-4c28-81b4-d3123d62d6e8

📥 Commits

Reviewing files that changed from the base of the PR and between 177c041 and 3e6e886.

⛔ Files ignored due to path filters (1)
  • lib/apify/youtube/__tests__/startYoutubeProfileScraping.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
📒 Files selected for processing (1)
  • lib/apify/youtube/startYoutubeProfileScraping.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/youtube-scrape-streams

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant Client as HTTP Client
    participant API as POST /api/socials/{id}/scrape
    participant Scraper as startYoutubeProfileScraping()
    participant Apify as Apify Actor SDK
    participant Webhook as Webhook Handler

    Note over Client,Webhook: YouTube Profile Scrape – Current State (after fix)

    Client->>API: POST /api/socials/{id}/scrape?posts=N
    API->>Scraper: startYoutubeProfileScraping(handle, posts)

    alt posts provided (e.g., N=20)
        Scraper->>Scraper: Build input = {<br/>  startUrls,<br/>  maxResults: N,<br/>  maxResultsShorts: N,<br/>  maxResultStreams: N,<br/>  ...DEFAULT_INPUT<br/>}
        Note over Scraper: NEW: streams enabled via posts value
    else posts omitted (legacy snapshot)
        Scraper->>Scraper: Build input = {<br/>  startUrls,<br/>  maxResults: 1,<br/>  maxResultsShorts: 0,<br/>  maxResultStreams: 0,<br/>  ...DEFAULT_INPUT<br/>}
        Note over Scraper: Streams still excluded (unchanged)
    end

    Scraper->>Apify: call("streamers/youtube-scraper", input, webhooks)
    Apify-->>Scraper: { runId, datasetId }
    Scraper-->>API: { runId, datasetId }
    API-->>Client: 200 { runId, datasetId }

    Note over Webhook: Later, when actor completes...
    Apify-->>Webhook: POST webhook with dataset items
    Webhook->>Webhook: Persist channel profile from items[0]
    Webhook-->>Apify: ACK
Loading

Auto-approved: Forwards posts to maxResultStreams so live streams are included with videos and shorts; tests updated.

Re-trigger cubic

...DEFAULT_INPUT,
startUrls: [{ url: targetUrl }],
// The legacy snapshot excludes Shorts; a requested posts depth includes them.
// The legacy snapshot excludes Shorts and streams; a requested posts depth includes both.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YAGNI - remove legacy notes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 5, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Auto-approved: Trivial forward of posts to maxResultStreams in YouTube scrape function, mirroring existing logic for videos and Shorts; test updated. Low impact, well-reasoned, no risk to core logic or infrastructure.

Re-trigger cubic

@sweetmantech

Copy link
Copy Markdown
Contributor Author

✅ Preview deployment test — streams come back

Deployment: dpl_4nZW1tTDwj4gSPZfLwuFJGimvCMP (commit 3e6e886c) → https://api-git-feat-youtube-scrape-streams-recoup.vercel.app

Test: POST /api/socials/{id}/scrape?posts=5 on the @mycowtf YouTube profile (sweetman), then polled GET /api/apify/runs/{runId}SUCCEEDED in ~90s.

Result — dataset is now 3-way, 15 items:

type count
video 5
shorts 5
stream 5 ← previously always 0

Stream items returned (newest-first from the Streams tab, each with views/likes/duration like regular videos):

streamed title duration
Jun 30 Executive Production with @cxy and @kismetcasa 28:59
Jun 22 🔴 LIVE: Build your own Record Label | Recoup Daily 32:37
Jun 2 Executive Production with @Blackdave and @cxy 26:53
May 22 🔴 LIVE: Build your own Record Label | Recoup Daily 1:11:18
May 15 🔴 LIVE: Build your own Record Label | Recoup Daily 58:46

This also resolves the open question from the PR description: the isLive: false default input is a search-mode filter only — it does not suppress stream items on channel-URL scrapes. Verify checkbox in the description is checked off.

🤖 Generated with Claude Code

@sweetmantech sweetmantech merged commit b91ed26 into main Jul 5, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant