English | Русский
A PHP client library for scraping data from Yandex services -- extract places and businesses from Yandex Maps, reviews from Yandex Maps, products from Yandex Market (Russia's largest marketplace), and real estate listings from Yandex Realty. Returns typed DTOs for each data type.
Powered by Apify actors under the hood.
composer require scraper-apis/yandex-scraperuse YandexParser\Client;
$client = new Client('your_apify_api_token');
// Search for restaurants in Moscow
$places = $client->scrapePlaces(
query: ['restaurant'],
location: 'Moscow',
maxResults: 50,
);
foreach ($places as $place) {
echo "{$place->title} — {$place->address}\n";
echo "Rating: {$place->rating} ({$place->reviewCount} reviews)\n";
if ($place->hasContactInfo()) {
echo "Phone: {$place->getFirstPhone()}\n";
echo "Email: {$place->email}\n";
}
if ($place->hasWebsite()) {
echo "Website: {$place->website}\n";
}
}The client wraps 4 specialized Apify actors, each optimized for a specific Yandex service.
Search Yandex Maps by keyword and location. Returns rich records with 60+ fields including contacts, ratings, schedule, photos, videos, AI-generated summaries, and more.
use YandexParser\Language;
$places = $client->scrapePlaces(
query: ['dentist', 'dental clinic'],
location: 'Saint Petersburg',
maxResults: 200,
language: Language::Russian,
options: [
'filterRating' => 4.5,
'filterOpenNow' => true,
'filterCardPayment' => true,
'enrichBusinessData' => true,
'maxPhotos' => 5,
],
);Available options for scrapePlaces():
| Option | Type | Description |
|---|---|---|
filterRating |
float |
Minimum rating threshold |
filterOpenNow |
bool |
Only currently open places |
filterOpen24h |
bool |
Only 24/7 places |
filterDelivery |
bool |
Has delivery service |
filterTakeaway |
bool |
Has takeaway option |
filterWifi |
bool |
WiFi available |
filterCardPayment |
bool |
Accepts card payments |
filterParking |
bool |
Has parking |
filterPetFriendly |
bool |
Pet-friendly establishment |
filterWheelchairAccess |
bool |
Wheelchair accessible |
filterGoodPlace |
bool |
Yandex "Good Place" badge |
filterMichelin |
bool |
Michelin-rated |
filterBusinessLunch |
bool |
Offers business lunch |
filterSummerTerrace |
bool |
Has summer terrace |
filterCuisine |
string |
Filter by cuisine type |
filterPriceCategory |
string |
Price category filter |
filterPriceMin |
int |
Minimum average check |
filterPriceMax |
int |
Maximum average check |
filterCategoryId |
string |
Filter by category ID |
filterChainId |
string |
Filter by chain ID |
customFilters |
array |
Custom filter parameters |
sortBy |
string |
Sort results |
sortOrigin |
string |
Sort origin point |
enrichBusinessData |
bool |
Fetch detailed business data |
maxPhotos |
int |
Max photos per place |
maxPosts |
int |
Max posts per place |
startUrls |
string[] |
Direct Yandex Maps URLs |
businessIds |
string[] |
Direct business IDs |
coordinates |
string |
Search center coordinates |
viewportSpan |
string |
Map viewport span |
category |
string |
Category filter |
Place DTO helpers:
$place->hasContactInfo(); // true if phones or email exist
$place->getFirstPhone(); // first phone number or null
$place->hasWebsite(); // true if website is set
$place->getCoordinates(); // ['lat' => float, 'lng' => float] or null
$place->isVerified(); // true if owner is verified
$place->hasVideos(); // true if videos array is not empty
$place->hasMenu(); // true if menu data is presentExtract reviews from Yandex Maps businesses. Accepts business URLs or numeric IDs. Returns flat one-row-per-review records with author info, business reply, and AI analysis.
use YandexParser\ReviewSort;
use YandexParser\Language;
$reviews = $client->scrapeReviews(
startUrls: [
'https://yandex.ru/maps/org/pushkin/1124715036/',
],
maxReviewsPerPlace: 500,
reviewSort: ReviewSort::Newest,
minRating: 1,
maxRating: 3,
language: Language::Russian,
);
foreach ($reviews as $review) {
echo "{$review->authorName}: {$review->rating}/5\n";
echo "{$review->text}\n";
if ($review->hasBusinessReply()) {
echo "Reply: {$review->getBusinessReplyText()}\n";
}
if ($review->hasPhotos()) {
echo "Photos: " . count($review->photos) . "\n";
}
}Parameters for scrapeReviews():
| Parameter | Type | Default | Description |
|---|---|---|---|
startUrls |
string[] |
[] |
Yandex Maps business URLs |
businessIds |
string[] |
[] |
Direct numeric business IDs |
maxReviewsPerPlace |
int |
0 |
Max reviews per place (0 = all) |
reviewSort |
ReviewSort |
Relevance |
Sort order |
minRating |
int |
0 |
Minimum star rating filter |
maxRating |
int |
0 |
Maximum star rating filter |
language |
Language |
English |
Response language |
At least one of startUrls or businessIds must be provided; otherwise an ApiException is thrown.
Review DTO helpers:
$review->hasBusinessReply(); // true if business replied
$review->getBusinessReplyText(); // reply text or null
$review->hasPhotos(); // true if review has photos
$review->hasVideos(); // true if review has videos
$review->isPositive(); // true if rating >= 4
$review->isNegative(); // true if rating <= 2
$review->hasTranslation(); // true if text translations existScrape product listings from Yandex Market -- Russia's largest e-commerce marketplace. Returns detailed product data with pricing, seller info, specifications, stock status, and YaBank card discounts.
use YandexParser\MarketSort;
use YandexParser\MarketRegion;
$products = $client->scrapeProducts(
query: 'ASUS laptop',
maxItems: 50,
region: MarketRegion::Moscow,
sort: MarketSort::PriceAsc,
options: [
'priceFrom' => 30000,
'priceTo' => 80000,
'includeReviews' => true,
],
);
foreach ($products as $product) {
echo "{$product->title}\n";
echo "Price: {$product->getPriceFormatted()}\n";
echo "Seller: {$product->sellerName} (rating: {$product->sellerRating})\n";
$discount = $product->getYaBankDiscount();
if ($discount !== null) {
echo "YaBank discount: {$discount}%\n";
}
if ($product->isInStock()) {
echo "In stock: {$product->stockCount} units\n";
}
}Available options for scrapeProducts():
| Option | Type | Description |
|---|---|---|
priceFrom |
int |
Minimum price filter |
priceTo |
int |
Maximum price filter |
categoryId |
string |
Filter by category |
enrichProducts |
bool |
Fetch detailed product data |
includeReviews |
bool |
Include product reviews |
proxyUrl |
string |
Custom proxy URL |
Product DTO helpers:
$product->hasReviews(); // true if reviews array is not empty
$product->hasImages(); // true if images array is not empty
$product->isInStock(); // true if product is available
$product->getPriceFormatted(); // "54,990 RUB" or null
$product->getYaBankDiscount(); // percentage discount (e.g. 10.0) or null
$product->hasUgcImages(); // true if user-generated images exist
$product->hasVideos(); // true if videos array is not emptyScrape property listings from Yandex Realty -- Russia's major real estate platform. Returns detailed listing data with pricing, location, property specs, seller info, price predictions, and more.
use YandexParser\DealType;
use YandexParser\PropertyCategory;
use YandexParser\RealtySort;
$listings = $client->scrapeListings(
location: 'Moscow',
dealType: DealType::Sell,
category: PropertyCategory::Apartment,
maxItems: 50,
sort: RealtySort::PriceAsc,
roomsTotal: ['1', '2'],
options: [
'priceMin' => 5000000,
'priceMax' => 15000000,
],
);
foreach ($listings as $listing) {
echo "{$listing->getAddress()} — {$listing->getPriceValue()} RUR\n";
echo "Area: {$listing->getAreaValue()} m², floor: {$listing->floorsOffered[0] ?? '?'}/{$listing->floorsTotal}\n";
if ($listing->hasPhones()) {
echo "Phone: {$listing->getFirstPhone()}\n";
}
if (!$listing->isFromOwner()) {
echo "Agency: {$listing->getSellerName()}\n";
}
$predicted = $listing->getPredictedPrice();
if ($predicted !== null) {
echo "Predicted: {$predicted['min']}–{$predicted['max']} RUR\n";
}
}Parameters for scrapeListings():
| Parameter | Type | Default | Description |
|---|---|---|---|
location |
string |
'Москва' |
City or region name |
dealType |
DealType |
Sell |
Deal type (sell or rent) |
category |
PropertyCategory |
Apartment |
Property category |
maxItems |
int |
100 |
Max listings to return |
sort |
RealtySort |
Relevance |
Sort order |
roomsTotal |
string[] |
[] |
Room filter: STUDIO, 1, 2, 3, PLUS_4 |
Available options for scrapeListings():
| Option | Type | Description |
|---|---|---|
priceMin |
int |
Minimum price filter |
priceMax |
int |
Maximum price filter |
areaMin |
int |
Minimum area (m²) |
areaMax |
int |
Maximum area (m²) |
floorMin |
int |
Minimum floor |
floorMax |
int |
Maximum floor |
agents |
bool |
Include agent listings |
regionId |
string |
Yandex region ID |
includePhones |
bool |
Fetch phone numbers |
includePriceHistory |
bool |
Fetch price change history |
Listing DTO helpers:
$listing->getPriceValue(); // price in rubles or null
$listing->getPriceCurrency(); // currency code (e.g. "RUR") or null
$listing->getPriceTrend(); // "INCREASED", "DECREASED", "UNCHANGED" or null
$listing->getPreviousPrice(); // previous price value or null
$listing->getAddress(); // full address string or null
$listing->getCoordinates(); // ['lat' => float, 'lng' => float] or null
$listing->getCity(); // city name or null
$listing->getRegion(); // region/federation name or null
$listing->getAreaValue(); // total area in m² or null
$listing->hasPhones(); // true if phone numbers available
$listing->getFirstPhone(); // first phone number or null
$listing->getWhatsAppPhones(); // WhatsApp numbers from author
$listing->hasImages(); // true if images exist
$listing->hasPriceHistory(); // true if price history available
$listing->getSellerName(); // seller/agency name or null
$listing->isFromOwner(); // true if listed by owner (not agency)
$listing->getBuildingYear(); // construction year or null
$listing->getPredictedPrice(); // ['min' => int, 'max' => int, 'value' => int] or nullSupported across places and reviews actors. 6 languages covering the Yandex Maps service area.
| Case | Value | Language |
|---|---|---|
Auto |
auto |
Auto-detect |
Russian |
ru |
Russian |
English |
en |
English |
Turkish |
tr |
Turkish |
Ukrainian |
uk |
Ukrainian |
Kazakh |
kk |
Kazakh |
| Case | Value | Description |
|---|---|---|
Relevance |
relevance |
Most relevant first |
Newest |
newest |
Newest first |
Highest |
highest |
Highest rating first |
Lowest |
lowest |
Lowest rating first |
| Case | Value | Description |
|---|---|---|
Default |
(none) | Default sorting |
Popular |
dpop |
Most popular first |
PriceAsc |
aprice |
Lowest price first |
PriceDesc |
dprice |
Highest price first |
Rating |
rating |
Highest rating first |
16 major Russian cities with their Yandex region IDs.
| Case | Value | City |
|---|---|---|
Moscow |
213 |
Moscow |
SaintPetersburg |
2 |
Saint Petersburg |
Yekaterinburg |
54 |
Yekaterinburg |
Kazan |
43 |
Kazan |
Novosibirsk |
65 |
Novosibirsk |
NizhnyNovgorod |
69 |
Nizhny Novgorod |
Samara |
51 |
Samara |
RostovOnDon |
39 |
Rostov-on-Don |
Krasnodar |
35 |
Krasnodar |
Chelyabinsk |
56 |
Chelyabinsk |
Ufa |
61 |
Ufa |
Perm |
47 |
Perm |
Voronezh |
62 |
Voronezh |
Volgograd |
63 |
Volgograd |
Krasnoyarsk |
66 |
Krasnoyarsk |
Omsk |
68 |
Omsk |
| Case | Value | Description |
|---|---|---|
Sell |
SELL |
Properties for sale |
Rent |
RENT |
Properties for rent |
| Case | Value | Description |
|---|---|---|
Apartment |
APARTMENT |
Apartments |
Rooms |
ROOMS |
Individual rooms |
House |
HOUSE |
Houses / cottages |
Lot |
LOT |
Land plots |
Commercial |
COMMERCIAL |
Commercial real estate |
Garage |
GARAGE |
Garages / parking |
| Case | Value | Description |
|---|---|---|
Relevance |
RELEVANCE |
Most relevant first |
Newest |
DATE_DESC |
Newest first |
PriceAsc |
PRICE |
Lowest price first |
PriceDesc |
PRICE_DESC |
Highest price first |
AreaAsc |
AREA |
Smallest area first |
AreaDesc |
AREA_DESC |
Largest area first |
CommissioningDate |
COMMISSIONING_DATE |
By commissioning date |
use YandexParser\Client;
use YandexParser\Config;
// Simple — just pass the API token
$client = new Client('your_apify_api_token');
// Advanced — override timeout or base URL
$client = new Client('token', new Config(
apiToken: 'token',
baseUrl: 'https://api.apify.com/v2',
timeout: 600,
));use YandexParser\Exception\ApiException;
use YandexParser\Exception\RateLimitException;
try {
$places = $client->scrapePlaces(query: ['cafe'], location: 'Kazan');
} catch (RateLimitException $e) {
// Retry after the suggested delay
sleep($e->retryAfter);
} catch (ApiException $e) {
echo "API error: {$e->getMessage()}\n";
}- PHP 8.3+
- Apify API token
- 2GIS Scraper PHP — scrape 2GIS places and reviews, real estate, jobs across 200+ cities in 20 countries
MIT