We use cookies to improve your experience. By using this site, you agree to our use of cookies. Privacy Policy (opens in new tab)
Access eToro's social layer programmatically — user profiles, social feeds, Pro Investor stats, and copy trading data through the API.
Finished: Explore Social Trading — all 3 steps
eToro's social trading platform generates rich data — user profiles, trade activity feeds, Pro Investor rankings, and copy trading relationships. The Social Feeds and Users Info APIs let you tap into this data programmatically to build analytics dashboards, leaderboards, and automated social strategies.
| API Surface | What It Provides | Key Endpoints |
|---|---|---|
| Social Feeds | Activity feed of trades, posts, and comments | /feeds/instruments/{instrumentId}, /feeds/users/{userId} |
| Users Info | Public profile data and trading stats | /users |
| Comments | Discussion threads on trades and instruments | /comments |
Retrieve public profile data including trading statistics, risk score, and performance history:
import { randomUUID } from "node:crypto";
const API_BASE = "https://public-api.etoro.com/api/v1";
async function getUserProfile(username) {
const response = await fetch(`${API_BASE}/users/${username}`, {
headers: {
"x-api-key": process.env.ETORO_API_KEY,
"x-user-key": process.env.ETORO_USER_KEY,
"x-request-id": randomUUID(),
},
});
const profile = await response.json();
return {
displayName: profile.displayName,
riskScore: profile.riskScore,
copiers: profile.copiers,
totalTrades: profile.totalTrades,
profitableWeeks: profile.profitableWeeksPct,
verified: profile.isVerified,
};
}
const trader = await getUserProfile("pro_investor_123");
console.log(`${trader.displayName} — Risk: ${trader.riskScore}, Copiers: ${trader.copiers}`);
The social feed streams trade activity, user posts, and market commentary:
import { randomUUID } from "node:crypto";
const API_BASE = "https://public-api.etoro.com/api/v1";
async function getSocialFeed(options = {}) {
const instrumentId = options.instrumentId;
if (!instrumentId) {
throw new Error("instrumentId is required for GET /feeds/instruments/{instrumentId}");
}
const params = new URLSearchParams({
limit: String(options.limit || 20),
...(options.type && { type: options.type }),
});
const response = await fetch(
`${API_BASE}/feeds/instruments/${instrumentId}?${params}`,
{
headers: {
"x-api-key": process.env.ETORO_API_KEY,
"x-user-key": process.env.ETORO_USER_KEY,
"x-request-id": randomUUID(),
},
});
return response.json();
}
// Get recent feed items for an instrument (resolve TSLA to instrumentId via /market-data/search first)
const teslaPosts = await getSocialFeed({
instrumentId: 123456,
limit: 10,
});
teslaPosts.items.forEach((item) => {
console.log(`[${item.type}] ${item.user.displayName}: ${item.text?.slice(0, 80)}...`);
});
| Type | Description |
|---|---|
trade_open |
User opened a new position |
trade_close |
User closed a position (includes P&L) |
post |
User published a text post |
comment |
User commented on an activity |
Combine user data and trading stats to build a ranked leaderboard of top performers:
import { randomUUID } from "node:crypto";
const API_BASE = "https://public-api.etoro.com/api/v1";
async function getTopTraders(count = 10) {
const response = await fetch(
`${API_BASE}/users/popular?limit=${count}&sort=gain`,
{
headers: {
"x-api-key": process.env.ETORO_API_KEY,
"x-user-key": process.env.ETORO_USER_KEY,
"x-request-id": randomUUID(),
},
}
);
const traders = await response.json();
return traders.map((t, i) => ({
rank: i + 1,
name: t.displayName,
gain: t.gain,
riskScore: t.riskScore,
copiers: t.copiers,
}));
}
const leaderboard = await getTopTraders(5);
console.table(leaderboard);
Read and post comments on trades and instruments:
import { randomUUID } from "node:crypto";
const API_BASE = "https://public-api.etoro.com/api/v1";
// Fetch comments for a specific instrument
async function getComments(instrumentId) {
const response = await fetch(
`${API_BASE}/comments?instrumentId=${instrumentId}&limit=20`,
{
headers: {
"x-api-key": process.env.ETORO_API_KEY,
"x-user-key": process.env.ETORO_USER_KEY,
"x-request-id": randomUUID(),
},
}
);
const comments = await response.json();
return comments.items.map((c) => ({
author: c.user.displayName,
text: c.body,
likes: c.likes,
timestamp: new Date(c.createdAt).toLocaleString(),
}));
}
Use social feed data to gauge market sentiment for an instrument:
import { randomUUID } from "node:crypto";
const API_BASE = "https://public-api.etoro.com/api/v1";
async function getSocialFeed(options = {}) {
const instrumentId = options.instrumentId;
if (!instrumentId) {
throw new Error("instrumentId is required for GET /feeds/instruments/{instrumentId}");
}
const params = new URLSearchParams({
limit: String(options.limit || 20),
...(options.type && { type: options.type }),
});
const response = await fetch(
`${API_BASE}/feeds/instruments/${instrumentId}?${params}`,
{
headers: {
"x-api-key": process.env.ETORO_API_KEY,
"x-user-key": process.env.ETORO_USER_KEY,
"x-request-id": randomUUID(),
},
}
);
return response.json();
}
async function analyzeSentiment(instrumentId, hours = 24) {
const since = new Date(Date.now() - hours * 60 * 60 * 1000).toISOString();
const feed = await getSocialFeed({
instrumentId,
limit: 100,
});
const trades = feed.items.filter(
(item) => item.type === "trade_open" && item.createdAt > since
);
const buys = trades.filter((t) => t.direction === "BUY").length;
const sells = trades.filter((t) => t.direction === "SELL").length;
const total = buys + sells;
return {
instrumentId,
period: `${hours}h`,
totalTrades: total,
buyPercentage: total > 0 ? ((buys / total) * 100).toFixed(1) : 0,
sellPercentage: total > 0 ? ((sells / total) * 100).toFixed(1) : 0,
sentiment: buys > sells ? "bullish" : sells > buys ? "bearish" : "neutral",
};
}
const sentiment = await analyzeSentiment(123456, 24);
console.log(
`${sentiment.instrumentId}: ${sentiment.sentiment} (${sentiment.buyPercentage}% buy / ${sentiment.sellPercentage}% sell)`
);
Retrieve information about copy trading relationships — who is copying whom, allocation amounts, and copy performance:
import { randomUUID } from "node:crypto";
const API_BASE = "https://public-api.etoro.com/api/v1";
// Get copy trading stats for a Pro Investor
async function getCopyStats(userId) {
const response = await fetch(`${API_BASE}/pi-data/copiers/${userId}`, {
headers: {
"x-api-key": process.env.ETORO_API_KEY,
"x-user-key": process.env.ETORO_USER_KEY,
"x-request-id": randomUUID(),
},
});
const stats = await response.json();
return {
totalCopiers: stats.totalCopiers,
totalCopiedAmount: stats.totalAllocated,
avgCopyDuration: stats.avgDurationDays,
topCopyAmounts: stats.copiers
?.slice(0, 5)
.map((c) => c.allocatedAmount),
};
}
Was this helpful?
Nice work finishing all 3 steps. Here are some next steps to keep building.