# Social Trading Data & Copy Trading

Access eToro's social layer programmatically — user profiles, social feeds, Pro Investor stats, and copy trading data through the API.

---


## Overview

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.

## Social Trading API Surfaces

| 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` |

## Fetching User Profiles

Retrieve public profile data including trading statistics, risk score, and performance history:

```javascript skip-test
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}`);
```

## Reading the Social Feed

The social feed streams trade activity, user posts, and market commentary:

```javascript skip-test
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)}...`);
});
```

### Feed Item Types

| 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 |

## Building a Trader Leaderboard

Combine user data and trading stats to build a ranked leaderboard of top performers:

```javascript skip-test
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);
```

## Working with Comments

Read and post comments on trades and instruments:

```javascript skip-test
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(),
  }));
}
```

## Sentiment Analysis Use Case

Use social feed data to gauge market sentiment for an instrument:

```javascript skip-test
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)`
);
```

## Copy Trading Data

Retrieve information about copy trading relationships — who is copying whom, allocation amounts, and copy performance:

```javascript skip-test
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),
  };
}
```

## Best Practices

1. **Respect user privacy** — Only access publicly available profile data. Do not attempt to scrape private information.
2. **Cache aggressively** — Social data changes less frequently than market data. Cache user profiles for 5–10 minutes.
3. **Rate limit awareness** — Social endpoints share the same rate limits as other API surfaces. Batch requests where possible and see the [Rate Limits documentation](https://api-portal.etoro.com/getting-started/rate-limits) for current limits.
4. **Handle missing data** — Not all users have public profiles. Check for null/undefined fields.
5. **Attribution** — If displaying user data publicly, follow eToro's data usage terms.

## Next Steps

- [Portfolio Management & Positions](/learn/portfolio-management-and-positions) — Track positions and P&L
- [Building an Algo Trading Bot](/learn/building-an-algo-trading-bot) — Automate trading strategies
- [Social Feeds API Reference](https://api-portal.etoro.com/api-reference) — Full endpoint documentation
