Привет, Хабр!
Когда я в первый раз разбирался, как тянуть котировки в Google Sheets, вокруг были сплошные IMPORTXML, XPath, парсинг HTML и прочая боль. Хотелось простого сценария: в ячейку передал тикер — получил актуальную цену с Мосбиржи. Тогда я собрал скрипт, который ходил напрямую в API MOEX из Google Apps Script, и всё это нормально жило какое‑то время.
С тех пор многое изменилось:
GOOGLEFINANCE по Мосбирже по‑прежнему мёртв.
Мосбиржа закрыла доступ к своему API с IP‑адресов Google (в том числе из Google Sheets / Apps Script).
Напрямую стучаться из таблиц в MOEX теперь нельзя — получаем ошибки/блокировку.
Поэтому я обновил решение:
поднял небольшой прокси‑сервер поверх официального ISS API Мосбиржи и переписал скрипт для таблиц, сделав его более универсальным — одна функция для ОФЗ, акций и фондов.

Что теперь происходит под капотом
Схема стала такой:
Google Таблица вызывает мою кастомную функцию, например:
=GET_PRICE("OFZ"; "SU26238RMFS9")
=GET_PRICE("STOCK"; "SBER")
=GET_PRICE("FUND"; "FXRL")
Google Apps Script делает HTTP‑запрос не напрямую в MOEX, а на мой небольшой backend (прокси).
Прокси‑сервер (у меня это FastAPI + httpx):
— ходит в официальное ISS API Мосбиржи;
— аккуратно парсит довольно нетривольный JSON;
— учитывает, что биржа может быть закрыта и приходится брать последнюю доступную цену из истории/статистики;
— кеширует ответ на 10 минут в файле, чтобы не душить API и не упираться в лимиты.
В ответ отдает компактный JSON:
{ "ticker": "SBER", "price": 279.53 }
Google Таблица забирает поле price и подставляет его в ячейку.
Эндпоинты прокси
На стороне сервера у меня три ручки (все GET):
GET /bond/{ticker} — ОФЗ / облигации
GET /stock/{ticker} — акции
GET /fund/{ticker} — фонды / ETF / БПИФы
Универсальная функция для Google Sheets
Теперь вместо трёх разных функций под каждый тип активов достаточно одной — GET_PRICE(type, ticker).
В Google Таблице заходите в Расширения → Apps Script, создаёте скрипт и вставляете туда:
function GET_PRICE(type, ticker) { if (!type || !ticker) { throw new Error('Нужно указать тип и тикер: GET_PRICE(type, ticker)'); }
var typeStr = String(type).trim().toLowerCase();
var tickerStr = String(ticker).trim().toUpperCase();
function GET_PRICE(type, ticker) {
if (!type !ticker) {
throw new Error('Нужно указать тип и тикер: GET_PRICE(type, ticker)');
}
var typeStr = String(type).trim().toLowerCase();
var tickerStr = String(ticker).trim().toUpperCase();
var path;
if (typeStr === 'ofz' typeStr === 'bond') {
path = 'bond';
} else if (typeStr === 'stock' typeStr === 'акция' typeStr === 'акции') {
path = 'stock';
} else if (typeStr === 'fund' typeStr === 'фонд' typeStr === 'фонды') {
path = 'fund';
} else {
throw new Error('Неизвестный тип актива: ' + type +
'. Ожидаю OFZ/STOCK/FUND (или bond/stock/fund).');
}
var url = 'https://exchange.technoquant.ru/' + path + '/' + encodeURIComponent(tickerStr);
var response = UrlFetchApp.fetch(url, {
method: 'get',
muteHttpExceptions: true
});
var code = response.getResponseCode();
var text = response.getContentText();
if (code !== 200) {
// Пробрасываем сообщение из твоего backend, если там HTTPException с detail
try {
var err = JSON.parse(text);
if (err && err.detail) {
throw new Error('Backend ' + code + ': ' + JSON.stringify(err.detail));
}
} catch (e) {
// не JSON — просто кидаем текст
}
throw new Error('Backend error: HTTP ' + code + ' — ' + text);
}
var data;
try {
data = JSON.parse(text);
} catch (e) {
throw new Error('Неверный JSON от backend: ' + text);
}
if (!data || typeof data.price !== 'number') {
throw new Error('Неверный формат ответа (ожидаю {"price": number}): ' + text);
}
return data.price;
}
Почему без прокси теперь никак
Раньше всё это можно было делать напрямую из Apps Script в API Мосбиржи. Сейчас:
IP‑пулы Google, с которых идут запросы из Google Sheets / Apps Script,
Мосбиржа фактически прикрыла.
В результате таблица напрямую в MOEX либо не достучится, либо упирается в блоки/ограничения.
Поэтому единственный нормальный вариант:
Либо держать свой прокси‑сервер, который:
живёт на «обычном» сервере с «нормальным» IP,
ходит в MOEX,
возвращает тебе аккуратный JSON.
Либо использовать какой‑то сторонний платный сервис‑агрегатор.
Я выбрал первый путь — поднял компактный FastAPI‑сервис, который:
знает три типа активов: ОФЗ, акции, фонды;
вытаскивает цену из всех нужных блоков ISS API;
кеширует ответы, чтобы не DDoSить биржу;
отдаёт простой { ticker, price }, с которым удобно работать в таблицах.