getListingPhotos
Extract photo URLs from Airbnb listings to access property images for verification, marketing, or research purposes.
Instructions
Extract photo URLs from an Airbnb listing
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Airbnb listing ID |
Implementation Reference
- photoTools.ts:4-14 (schema)Defines the tool schema including input validation for the listing ID parameter.{ name: 'getListingPhotos', description: 'Extract photo URLs from an Airbnb listing', inputSchema: { type: 'object', properties: { id: { type: 'string', description: 'Airbnb listing ID' }, }, required: ['id'], }, },
- index.ts:138-141 (registration)Registers the getListingPhotos tool by including photoAnalysisTools in the main AIRBNB_TOOLS array used for listing tools.AIRBNB_SEARCH_TOOL, AIRBNB_LISTING_DETAILS_TOOL, ...photoAnalysisTools, ];
- index.ts:666-670 (registration)Registers the dispatching logic for getListingPhotos tool calls in the main CallToolRequestHandler switch statement.case "getListingPhotos": case "analyzeListingPhotos": { result = await handlePhotoAnalysisTool(request.params.name, request.params.arguments); break; }
- photoTools.ts:28-83 (handler)Main handler function for getListingPhotos tool: validates input, extracts photos, formats and returns MCP response.export async function handlePhotoAnalysisTool(toolName: string, toolInput: any) { try { const listingId = toolInput.id; if (!listingId) { return { content: [{ type: 'text', text: JSON.stringify({ error: 'Listing ID required' }) }], isError: true, }; } const photos = await extractListingPhotos(listingId); if (toolName === 'getListingPhotos') { return { content: [ { type: 'text', text: JSON.stringify({ success: photos.extractionSuccess, photoCount: photos.photoCount, photoUrls: photos.photoUrls, }), }, ], isError: !photos.extractionSuccess, }; } if (toolName === 'analyzeListingPhotos') { return { content: [ { type: 'text', text: JSON.stringify({ success: photos.extractionSuccess, photoCount: photos.photoCount, analysisPrompt: formatPhotosForAnalysis(photos), photoUrls: photos.photoUrls, }), }, ], isError: !photos.extractionSuccess, }; } return { content: [{ type: 'text', text: JSON.stringify({ error: 'Unknown tool' }) }], isError: true, }; } catch (error) { return { content: [{ type: 'text', text: JSON.stringify({ error: (error instanceof Error ? error.message : 'Unknown error') }) }], isError: true, }; } }
- photoAnalyzer.ts:4-42 (helper)Helper function that performs the actual web scraping to extract photo URLs from the Airbnb listing page.export async function extractListingPhotos(listingId: string) { try { const url = `https://www.airbnb.com/rooms/${listingId}`; const response = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' }, }); if (!response.ok) throw new Error(`HTTP ${response.status}`); const html = await response.text(); const $ = cheerio.load(html); const photoUrls: string[] = []; $('img[src*="airbnb"]').each((_: any, el: any) => { const src = $(el).attr('src'); const alt = $(el).attr('alt'); if (src && alt?.includes('photo') && photoUrls.length < 50) { if (!photoUrls.includes(src)) photoUrls.push(src); } }); return { listingId, photoUrls, photoCount: photoUrls.length, extractionSuccess: photoUrls.length > 0, timestamp: new Date().toISOString(), }; } catch (error) { return { listingId, photoUrls: [], photoCount: 0, extractionSuccess: false, error: (error instanceof Error ? error.message : 'Unknown error'), timestamp: new Date().toISOString(), }; } }