Skip to content

Commit 003d532

Browse files
authored
feat(apify): IG reel scraper added
1 parent c258779 commit 003d532

11 files changed

Lines changed: 369 additions & 21 deletions

File tree

packages/bubble-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bubblelab/bubble-core",
3-
"version": "0.1.321",
3+
"version": "0.1.322",
44
"type": "module",
55
"license": "Apache-2.0",
66
"main": "./dist/index.js",
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { z } from 'zod';
2+
import { InstagramPostSchema } from './instagram-scraper.js';
3+
4+
// ============================================================================
5+
// INSTAGRAM REEL SCRAPER SCHEMAS
6+
// ============================================================================
7+
8+
export const InstagramReelScraperInputSchema = z.object({
9+
username: z
10+
.array(z.string())
11+
.min(
12+
1,
13+
'At least one username, profile URL, profile ID, or reel URL is required'
14+
)
15+
.describe(
16+
'Instagram usernames, profile URLs, profile IDs, or direct reel URLs. Examples: ["ryanbailey.cb"], ["https://www.instagram.com/ryanbailey.cb/"], ["https://www.instagram.com/p/DXIlvPbj2PY/"]'
17+
),
18+
19+
resultsLimit: z
20+
.number()
21+
.min(1)
22+
.default(20)
23+
.describe('Maximum number of reels to scrape per profile (min 1)'),
24+
25+
onlyPostsNewerThan: z
26+
.string()
27+
.optional()
28+
.describe(
29+
'Only return reels posted on or after this date. Accepts YYYY-MM-DD, ISO timestamp, or relative time like "1 day" / "2 weeks"'
30+
),
31+
32+
skipPinnedPosts: z
33+
.boolean()
34+
.default(false)
35+
.optional()
36+
.describe('Exclude pinned reels from the results'),
37+
38+
includeSharesCount: z
39+
.boolean()
40+
.default(false)
41+
.optional()
42+
.describe('Extract the number of shares for each reel (paid add-on)'),
43+
44+
includeTranscript: z
45+
.boolean()
46+
.default(false)
47+
.optional()
48+
.describe(
49+
'Extract an auto-generated text transcript of the reel audio (paid add-on)'
50+
),
51+
52+
includeDownloadedVideo: z
53+
.boolean()
54+
.default(false)
55+
.optional()
56+
.describe('Include a direct MP4 download URL for each reel (paid add-on)'),
57+
});
58+
59+
// Reel scraper extends the base post schema with reel-specific fields
60+
export const InstagramReelScraperItemSchema = InstagramPostSchema.extend({
61+
inputUrl: z
62+
.string()
63+
.optional()
64+
.describe('Original input profile or reel URL'),
65+
ownerFullName: z.string().optional().describe('Reel owner full name'),
66+
sharesCount: z
67+
.number()
68+
.optional()
69+
.describe('Number of shares (only present when includeSharesCount=true)'),
70+
videoPlayCount: z.number().optional().describe('Number of video plays'),
71+
videoDuration: z.number().optional().describe('Reel length in seconds'),
72+
videoUrl: z.string().optional().describe('CDN video URL'),
73+
downloadedVideo: z
74+
.string()
75+
.optional()
76+
.describe(
77+
'Direct MP4 download URL (only present when includeDownloadedVideo=true)'
78+
),
79+
transcript: z
80+
.string()
81+
.optional()
82+
.describe(
83+
'Auto-generated speech transcript (only present when includeTranscript=true)'
84+
),
85+
firstComment: z.string().optional().describe('First/top comment text'),
86+
latestComments: z
87+
.array(z.unknown())
88+
.optional()
89+
.describe('Array of latest comments with owner, text, likes, replies'),
90+
coauthorProducers: z
91+
.array(z.unknown())
92+
.optional()
93+
.describe('Co-creator information'),
94+
musicInfo: z
95+
.object({
96+
artist_name: z.string().optional(),
97+
song_name: z.string().optional(),
98+
uses_original_audio: z.boolean().optional(),
99+
audio_id: z.string().optional(),
100+
})
101+
.passthrough()
102+
.optional()
103+
.describe('Music/audio information for the reel'),
104+
});

packages/bubble-core/src/bubbles/service-bubble/apify/apify-scraper.schema.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import {
66
InstagramHashtagScraperInputSchema,
77
InstagramHashtagScraperItemSchema,
88
} from './actors/instagram-hashtag-scraper.js';
9+
import {
10+
InstagramReelScraperInputSchema,
11+
InstagramReelScraperItemSchema,
12+
} from './actors/instagram-reel-scraper.js';
913
import {
1014
LinkedInProfilePostsInputSchema,
1115
LinkedInProfilePostsOutputSchema,
@@ -66,6 +70,14 @@ export const APIFY_ACTOR_SCHEMAS = {
6670
documentation: 'https://apify.com/apify/instagram-hashtag-scraper',
6771
category: 'social-media',
6872
},
73+
'apify/instagram-reel-scraper': {
74+
input: InstagramReelScraperInputSchema,
75+
output: InstagramReelScraperItemSchema,
76+
description:
77+
'Scrape Instagram reels from profiles or direct reel URLs with optional transcript, share counts, and downloaded MP4 URLs',
78+
documentation: 'https://apify.com/apify/instagram-reel-scraper',
79+
category: 'social-media',
80+
},
6981
'apimaestro/linkedin-profile-posts': {
7082
input: LinkedInProfilePostsInputSchema,
7183
output: LinkedInProfilePostsOutputSchema,

packages/bubble-core/src/bubbles/service-bubble/apify/apify.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ const ApifyParamsSchema = z.object({
5252
timeout: z
5353
.number()
5454
.min(1000)
55-
.max(500000)
55+
.max(1800000)
5656
.optional()
5757
.default(300000)
5858
.describe(
59-
'Maximum time to wait for actor completion in milliseconds (default: 120000)'
59+
'Maximum time to wait for actor completion in milliseconds (default: 300000 = 5 min, max: 1800000 = 30 min). Long-running actors (e.g., apify/instagram-reel-scraper with transcripts) need >300s.'
6060
),
6161
credentials: z
6262
.record(z.nativeEnum(CredentialType), z.string())

0 commit comments

Comments
 (0)