Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions javascript/amazon-global-price-comparison/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Browserbase credentials - get these from https://www.browserbase.com/settings
BROWSERBASE_API_KEY=your_browserbase_api_key
66 changes: 66 additions & 0 deletions javascript/amazon-global-price-comparison/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Amazon Global Price Comparison

## AT A GLANCE

- Goal: compare Amazon product prices across multiple countries using geolocation proxies.
- Uses Browserbase's managed proxy infrastructure to route traffic through different geographic locations (US, UK, Germany, France, Italy, Spain).
- Extracts structured product data (name, price, rating, reviews) using Stagehand's extraction capabilities with Zod schema validation.
- Sequential processing shows how different proxy locations return different pricing from the same Amazon search.
- Docs → https://docs.browserbase.com/features/proxies

## GLOSSARY

- geolocation proxies: route traffic through specific geographic locations (city, country) to access location-specific content and pricing
Docs → https://docs.browserbase.com/features/proxies#set-proxy-geolocation
- extract: extract structured data from web pages using natural language instructions and Zod schemas
Docs → https://docs.stagehand.dev/basics/extract
- proxies: Browserbase's managed proxy infrastructure supporting 201+ countries for geolocation-based routing
Docs → https://docs.browserbase.com/features/proxies

## QUICKSTART

1. cd amazon-global-price-comparison
2. pnpm install
3. cp .env.example .env
4. Add your Browserbase API key to .env
5. pnpm start

## EXPECTED OUTPUT

- Creates Browserbase sessions with geolocation proxies for each country (US, UK, DE, FR, IT, ES)
- Navigates to Amazon search results through location-specific proxies
- Extracts product name, price, rating, and review count for each location
- Displays formatted comparison table showing price differences across countries
- Outputs JSON results for programmatic use

## COMMON PITFALLS

- Browserbase Developer plan or higher is required to use proxies
- "Cannot find module": ensure all dependencies are installed (`pnpm install`)
- Missing credentials: verify .env contains BROWSERBASE_API_KEY
- Geolocation fields are case-insensitive (city, country can be any case)
- Amazon may show different products in different regions - comparison works best for globally available products
- ERR_TUNNEL_CONNECTION_FAILED: indicates either a temporary proxy hiccup or a site unsupported by built-in proxies

## USE CASES

• Price arbitrage: Find the best country to purchase products from for international shipping
• Market research: Compare pricing strategies across different Amazon regions
• Competitive analysis: Monitor how competitors price products globally
• Travel shopping: Check prices before international trips to plan purchases

## NEXT STEPS

• Add more countries: Extend the COUNTRIES array with additional regions (Japan, Australia, Canada, etc.)
• Currency conversion: Add real-time currency conversion to normalize prices for comparison
• Price tracking: Store results over time to track price changes across regions
• Email alerts: Send notifications when price drops below a threshold in any country

## HELPFUL RESOURCES

📚 Stagehand Docs: https://docs.stagehand.dev/v3/first-steps/introduction
🎮 Browserbase: https://www.browserbase.com
💡 Try it out: https://www.browserbase.com/playground
🔧 Templates: https://www.browserbase.com/templates
📧 Need help? support@browserbase.com
💬 Discord: http://stagehand.dev/discord
199 changes: 199 additions & 0 deletions javascript/amazon-global-price-comparison/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// Amazon Global Price Comparison - See README.md for full documentation
import "dotenv/config";
import { Stagehand } from "@browserbasehq/stagehand";
import { z } from "zod";
// Schema for a single product with structured extraction fields
const ProductSchema = z.object({
name: z.string().describe("The full product title/name"),
price: z
.string()
.describe("The product price including currency symbol (e.g., '$29.99', '29,99 EUR', '29.99 GBP'). If no price is visible, return 'N/A'"),
rating: z.string().describe("The star rating (e.g., '4.5 out of 5 stars')"),
reviews_count: z.string().describe("The number of customer reviews (e.g., '1,234')"),
product_url: z
.string()
.describe("The full href URL link to the product detail page (starting with https:// or /dp/)"),
});
// Schema for extracting multiple products from search results
const ProductsSchema = z.object({
products: z.array(ProductSchema).describe("Array of products from search results"),
});
// Supported countries for price comparison
// Add or remove countries as needed - see https://docs.browserbase.com/features/proxies for available geolocations
const COUNTRIES = [
{ name: "United States", code: "US", city: undefined, currency: "USD" },
{ name: "United Kingdom", code: "GB", city: "LONDON", currency: "GBP" },
{ name: "Germany", code: "DE", city: "BERLIN", currency: "EUR" },
{ name: "France", code: "FR", city: "PARIS", currency: "EUR" },
{ name: "Italy", code: "IT", city: "ROME", currency: "EUR" },
{ name: "Spain", code: "ES", city: "MADRID", currency: "EUR" },
];
/**
* Fetches products from Amazon for a specific country using geolocation proxy
* Uses Browserbase's managed proxy infrastructure to route traffic through the target country
* This ensures Amazon shows location-specific pricing and availability
*/
async function getProductsForCountry(searchQuery, country, resultsCount = 3) {
console.log(`\n=== Searching Amazon for "${searchQuery}" in ${country.name} ===`);
// Build geolocation config for proxy routing
const geolocation = {
country: country.code,
};
if (country.city) {
geolocation.city = country.city;
}
// Initialize Stagehand with geolocation proxy configuration
// This ensures all browser traffic routes through the specified geographic location
const stagehand = new Stagehand({
env: "BROWSERBASE",
verbose: 0,
// 0 = errors only, 1 = info, 2 = debug
// (When handling sensitive data like passwords or API keys, set verbose: 0 to prevent secrets from appearing in logs.)
// https://docs.stagehand.dev/configuration/logging
browserbaseSessionCreateParams: {
proxies: [
{
type: "browserbase", // Use Browserbase's managed proxy infrastructure for reliable geolocation routing
geolocation,
},
],
},
});
try {
console.log(`Initializing browser session with ${country.name} proxy...`);
await stagehand.init();
const page = stagehand.context.pages()[0];
// Alternative: Skip the search bar and go straight to results by building the search URL.
// Uncomment below to use direct navigation instead of stagehand.act() typing + clicking.
// const searchUrl = `https://www.amazon.com/s?k=${encodeURIComponent(searchQuery)}`;
// console.log(`Navigating to: ${searchUrl}`);
// await page.goto(searchUrl, { waitUntil: "domcontentloaded", timeout: 60000 });
// Navigate to Amazon homepage to begin search
console.log(`[${country.name}] Navigating to Amazon...`);
await page.goto("https://www.amazon.com", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
// Perform search using natural language actions
console.log(`[${country.name}] Searching for: ${searchQuery}`);
await stagehand.act(`Type "${searchQuery}" into the search bar`);
await stagehand.act("Click the search button");
// Extract products from search results using Stagehand's structured extraction
console.log(`[${country.name}] Extracting top ${resultsCount} products...`);
const extractionResult = await stagehand.extract(`Extract the first ${resultsCount} product search results from this Amazon page. For each product, extract:
1. name: the full product title
2. price: the displayed price WITH currency symbol (like $599.99 or 599,99 EUR). If no price shown, use "N/A"
3. rating: the star rating text (like "4.5 out of 5 stars")
4. reviews_count: the number of reviews (like "2,508")
5. product_url: the href link to the product page (starts with /dp/ or https://)

Only extract actual product listings, skip sponsored ads or recommendations.`, ProductsSchema);
// Clean up products - ensure price is never null and URLs are absolute
const cleanedProducts = extractionResult.products.map((p) => ({
...p,
price: p.price || "N/A",
product_url: p.product_url?.startsWith("http")
? p.product_url
: p.product_url?.startsWith("/")
? `https://www.amazon.com${p.product_url}`
: p.product_url || "N/A",
}));
console.log(`Found ${cleanedProducts.length} products in ${country.name}`);
await stagehand.close();
return {
country: country.name,
countryCode: country.code,
currency: country.currency,
products: cleanedProducts.slice(0, resultsCount),
};
}
catch (error) {
console.error(`Error fetching products from ${country.name}:`, error);
await stagehand.close();
return {
country: country.name,
countryCode: country.code,
currency: country.currency,
products: [],
error: error instanceof Error ? error.message : String(error),
};
}
}
/**
* Displays results in a formatted comparison table
* Shows product name, price, rating, and review count for each country
*/
function displayComparisonTable(results) {
console.log("\n" + "=".repeat(100));
console.log("PRICE COMPARISON ACROSS COUNTRIES");
console.log("=".repeat(100));
// Find the first successful result to get product count
const successfulResult = results.find((r) => r.products.length > 0);
if (!successfulResult) {
console.log("No products found in any country.");
return;
}
// Display results for each product position
const maxProducts = Math.max(...results.map((r) => r.products.length));
for (let i = 0; i < maxProducts; i++) {
console.log(`\n--- Product ${i + 1} ---`);
// Find the first available product name for this position
const productName = results.find((r) => r.products[i])?.products[i]?.name;
if (productName) {
const truncatedName = productName.length > 80 ? productName.slice(0, 77) + "..." : productName;
console.log(`Product: ${truncatedName}`);
}
console.log("\nPrices by Country:");
console.log("-".repeat(70));
for (const result of results) {
const countryPad = result.country.padEnd(20);
if (result.error) {
console.log(` ${countryPad} | Error: ${result.error}`);
}
else if (result.products[i]) {
const product = result.products[i];
const price = product.price || "N/A";
const pricePad = price.padEnd(18);
const ratingShort = product.rating?.split(" out")[0] || "N/A";
const ratingPad = ratingShort.padEnd(6);
const reviews = product.reviews_count || "N/A";
console.log(` ${countryPad} | ${pricePad} | ${ratingPad} stars | ${reviews} reviews`);
}
else {
console.log(` ${countryPad} | Not available in this country`);
}
}
}
console.log("\n" + "=".repeat(100));
}
async function main() {
// Configure search parameters
const searchQuery = "iPhone 15 Pro Max 256GB";
const resultsCount = 3;
console.log("=".repeat(60));
console.log("AMAZON PRICE COMPARISON - GEOLOCATION PROXY DEMO");
console.log("=".repeat(60));
console.log(`Search Query: ${searchQuery}`);
console.log(`Results per country: ${resultsCount}`);
console.log(`Countries: ${COUNTRIES.map((c) => c.code).join(", ")}`);
console.log("=".repeat(60));
// Process all countries concurrently for faster execution
// Each country uses its own browser session, so they can run in parallel
console.log(`\nFetching prices from ${COUNTRIES.length} countries concurrently...`);
const results = await Promise.all(COUNTRIES.map((country) => getProductsForCountry(searchQuery, country, resultsCount)));
// Display formatted comparison table
displayComparisonTable(results);
// Output JSON results for programmatic use
console.log("\n--- JSON OUTPUT ---");
console.log(JSON.stringify(results, null, 2));
console.log("\n=== Price comparison completed ===");
}
main().catch((err) => {
console.error("Application error:", err);
console.error("\nCommon issues:");
console.error(" - Check .env file has BROWSERBASE_API_KEY");
console.error(" - Verify geolocation proxy locations are valid (see https://docs.browserbase.com/features/proxies)");
console.error(" - Ensure you have sufficient Browserbase credits");
console.error("Docs: https://docs.stagehand.dev/v3/first-steps/introduction");
process.exit(1);
});
12 changes: 12 additions & 0 deletions javascript/amazon-global-price-comparison/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "amazon-global-price-comparison-template",
"type": "module",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@browserbasehq/stagehand": "latest",
"dotenv": "^16.4.7",
"zod": "latest"
}
}
2 changes: 2 additions & 0 deletions javascript/amazon-product-scraping/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Browserbase Configuration
BROWSERBASE_API_KEY=your_browserbase_api_key
62 changes: 62 additions & 0 deletions javascript/amazon-product-scraping/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Stagehand + Browserbase: Amazon Product Scraping

## AT A GLANCE

- Goal: scrape the first 3 Amazon search results for a given query and return structured product data.
- AI-Powered Search: uses Stagehand `act` to type in the search bar and click search (or optionally navigate directly to the search URL).
- Structured Extraction: uses `extract` with a Zod schema to get product name, price, rating, review count, and product URL.
- Model: uses `google/gemini-2.5-flash` for fast, cost-effective automation.
Docs → https://docs.stagehand.dev

## GLOSSARY

- act: perform UI actions from a prompt (type in search bar, click search)
Docs → https://docs.stagehand.dev/basics/act
- extract: pull structured data from pages using schemas
Docs → https://docs.stagehand.dev/basics/extract

## QUICKSTART

1. cd typescript/amazon-product-scraping
2. npm install
3. cp .env.example .env (or create .env with required keys)
4. Add BROWSERBASE_API_KEY to .env
5. Optionally edit SEARCH_QUERY in index.ts
6. npm start

## EXPECTED OUTPUT

- Initializes Stagehand session with Browserbase
- Displays live session link for monitoring
- Navigates to Amazon and performs search (or direct URL navigation if uncommented)
- Extracts the first 3 products with name, price, rating, reviews count, and product URL
- Outputs JSON to console
- Closes session cleanly

## COMMON PITFALLS

- "Cannot find module": ensure npm install completed
- Missing credentials: verify .env contains BROWSERBASE_API_KEY
- Amazon layout changes: extraction may need prompt/schema updates if Amazon changes their search results UI
- Find more information on your Browserbase dashboard → https://www.browserbase.com/sign-in

## USE CASES

• Price monitoring: Scrape top results for a product query to track prices and availability over time.
• Competitor research: Extract product titles, ratings, and review counts for comparison.
• Catalog building: Pull structured product data for feeds, dashboards, or internal tools.

## NEXT STEPS

• Switch to direct URL: Uncomment the URL-based search block in index.ts for faster runs without LLM search actions.
• Parameterize query: Accept SEARCH_QUERY from CLI or env for different products without editing code.
• Paginate: Extend extraction to multiple pages or increase the number of products per run.

## HELPFUL RESOURCES

📚 Stagehand Docs: https://docs.stagehand.dev
🎮 Browserbase: https://www.browserbase.com
💡 Try it out: https://www.browserbase.com/playground
🔧 Templates: https://www.browserbase.com/templates
📧 Need help? support@browserbase.com
💬 Discord: http://stagehand.dev/discord
Loading
Loading