Skip to main content
Glama

extract_demographics

Analyze user engagement on Instagram by extracting demographic insights from accounts or posts. Input a URL and sample size to identify audience characteristics for strategic planning.

Instructions

Extract demographic insights from users engaged with a post or account

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
accountOrPostUrlYesInstagram account handle or post URL to analyze
sampleSizeNoNumber of users to sample for demographic analysis (default: 50)

Implementation Reference

  • Main handler function for the 'extract_demographics' tool. Determines if input is account or post, fetches likers or followers, samples users, and computes basic demographics (placeholder analysis).
    private async handleExtractDemographics(args: ExtractDemographicsArgs) { console.error('[Tool] handleExtractDemographics called with args:', args); const { accountOrPostUrl, sampleSize = 50 } = args; // Determine if it's a post URL or username let targetId: string; let targetType: 'account' | 'post'; if (isValidPostUrl(accountOrPostUrl)) { targetType = 'post'; const mediaId = await this.getMediaIdFromUrl(accountOrPostUrl); if (!mediaId) { throw new McpError(ErrorCode.InvalidParams, 'Could not extract media ID from post URL.'); } targetId = mediaId; console.error(`[Tool] Extracting demographics from post: ${targetId}`); } else if (isValidUsername(accountOrPostUrl)) { targetType = 'account'; try { const userId = await this.ig.user.getIdByUsername(accountOrPostUrl); targetId = String(userId); // Convert number userId to string for targetId console.error(`[Tool] Extracting demographics from account followers: ${accountOrPostUrl} (ID: ${targetId})`); } catch(e: any) { if (e.name === 'IgNotFoundError') { throw new McpError(ErrorCode.InvalidParams, `Account ${accountOrPostUrl} not found.`); } throw new McpError(ErrorCode.InternalError, `Failed to get user ID for ${accountOrPostUrl}: ${e.message}`); } } else { throw new McpError(ErrorCode.InvalidParams, 'Invalid input. Provide a valid Instagram username or post URL.'); } try { let users: any[] = []; if (targetType === 'post') { // Get likers or commenters as sample console.error(`[Tool Debug] Attempting to fetch likers for media ID: ${targetId}`); const likersResponse = await this.ig.media.likers(targetId); let fetchedUsers: any[] = likersResponse.users || []; // Access users from the response object // Manual pagination simulation (if needed and possible, likers might not support feed pagination) // The private API might not offer easy pagination for likers beyond the initial batch. // For simplicity, we'll just use the first batch returned. /* let fetchedUsers: any[] = []; do { // Feed results are usually directly items const items = await likersFeed.items(); fetchedUsers = fetchedUsers.concat(items); if (fetchedUsers.length >= sampleSize) break; await new Promise(resolve => setTimeout(resolve, 200 + Math.random() * 300)); } while (likersFeed.isMoreAvailable()); */ users = fetchedUsers.slice(0, sampleSize); console.error(`[Tool] Fetched ${users.length} likers from post ${targetId}`); } else { // targetType === 'account' const userIdNum = parseInt(targetId, 10); const followersFeed = this.ig.feed.accountFollowers(userIdNum); let fetchedUsers: any[] = []; do { const items = await followersFeed.items(); fetchedUsers = fetchedUsers.concat(items); if (fetchedUsers.length >= sampleSize) break; await new Promise(resolve => setTimeout(resolve, 200 + Math.random() * 300)); } while (followersFeed.isMoreAvailable()); users = fetchedUsers.slice(0, sampleSize); console.error(`[Tool] Fetched ${users.length} followers from account ${accountOrPostUrl}`); } if (users.length === 0) { return { results: { message: 'No users found to analyze (post might have no likes/comments, or account has no followers/is private).', demographics: {} } }; } // Placeholder for actual demographic analysis const demographics = { sampleAnalyzed: users.length, commonLocationsGuess: ['Unknown'], genderDistributionGuess: { male: 0.4, female: 0.4, unknown: 0.2 }, accountTypes: { private: users.filter(u => u.is_private).length / users.length, verified: users.filter(u => u.is_verified).length / users.length, }, sampleUserProfiles: users.slice(0, 5).map(u => ({ username: u.username, fullName: u.full_name, isPrivate: u.is_private, })) }; return { results: { demographics } }; } catch (error: any) { console.error(`[API Error] Failed to extract demographics for ${accountOrPostUrl}:`, error.message || error); if (error.name === 'IgNotFoundError') { throw new McpError(ErrorCode.InvalidParams, `${targetType === 'post' ? 'Post' : 'Account'} not found or access denied.`); } throw new McpError(ErrorCode.InternalError, `Failed to fetch users for demographic analysis: ${error.message}`); } }
  • TypeScript interface defining the input arguments for the extract_demographics tool.
    interface ExtractDemographicsArgs { accountOrPostUrl: string; sampleSize?: number; }
  • src/index.ts:172-189 (registration)
    Tool registration in the ListTools response, including name, description, and JSON input schema.
    { name: 'extract_demographics', description: 'Extract demographic insights from users engaged with a post or account', inputSchema: { type: 'object', properties: { accountOrPostUrl: { type: 'string', description: 'Instagram account handle or post URL to analyze', }, sampleSize: { type: 'number', description: 'Number of users to sample for demographic analysis (default: 50)', }, }, required: ['accountOrPostUrl'], }, },
  • src/index.ts:270-271 (registration)
    Dispatch case in the CallToolRequestSchema handler that routes to the specific handler function.
    case 'extract_demographics': return await this.handleExtractDemographics(args as unknown as ExtractDemographicsArgs);

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Bob-lance/instagram-engagement-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server