Documentation

Build with VRChat Legends

Everything about profiles, community roles, and the platform - plus a full API reference, OAuth 2.0 sign-in for your own apps, and copy-paste embeds. Public, no sign-in needed.

01

Introduction

VRChat Legends is a community-driven project that documents the players, groups, worlds, and stories of VRChat. This site is your hub for finding and celebrating the people who make VRChat special.

Everything on the site is designed to load fast and stay available. Even if something goes wrong behind the scenes, pages will still show up with cached data so you never hit a blank screen.

Legend Profiles

Curated bios, history, gallery and links

Community profiles

VRChat-verified, unlisted pages (direct link only)

Our Worlds

VRChat worlds created by our community

Community

Groups, events, team and Patreon supporters

02

Legend Profiles

Each Legend has their own profile page where you can learn about who they are, what they've done in VRChat, and see their photos, videos, and links. Here's what you'll find on a typical profile:

About / Bio

A quick intro about the Legend

History

Their VRChat journey, first steps, and world creation

Biography

Extended personal background

Quotes

Memorable things they've said

Gallery

Photos you can click to view fullscreen

Videos

Embedded YouTube videos

Links

Social media and other external links

Worlds

VRChat worlds they've created or are connected to

Details

Species, profession, colors, and other fun facts

Profiles with founder: true get a special crown badge and are sorted first on the Legends list. Profiles with verified: true appear before unverified legends. Community user profiles (see the next chapter) never appear in this list.

03

Community user profiles

Anyone signed in with Discord can start a community user profile at /create-profile. These pages are separate from official Legend profiles: they are not curated for the Legends directory and do not affect Featured Legends.

VRChat verification

  1. 1Sign in with Discord and open the create profile page.
  2. 2Enter your VRChat display username or your usr_… user id.
  3. 3Click Generate Code and paste the code into your VRChat bio.
  4. 4Click Check Code after saving your bio. If the code matches, your profile is created and linked.

Visibility and discovery

  • Always unlisted; only people with the link can open the page.
  • Not shown on the Legends tab or Featured Legends.
  • Not indexed for search (noindex). You can toggle section visibility on your page; curated custom tags are not available on user-created profiles.
  • Stricter limits: 3 gallery images, 3 YouTube embeds, 10 worlds, 10 avatars, 5 external links. Display name may change once every 14 days; up to 3 avatar or banner image changes per hour.
  • Read-only iframe embeds (profile card, likes/views counters, worlds, avatars, videos, gallery, profile comments) work for community profile IDs the same way as full Legends - copy them from Edit Profile → Media & Links.
  • Badges: World Creator, Avatar Creator, Content Creator, Streamer; staff may add Early Adopter.

Reporting

Community profile pages include Report Profile (not on your own page). Reports go to the configured Discord moderation channel with profile link, VRChat identity, reporter, category, details, and time. Authenticated POST /api/players/:id/report expects JSON category (e.g. harassment, hate, nsfw, spam, impersonation, self_harm, other) and details (required, max 1000 chars).

Invite merge

If you already have a community profile and receive a full Legends invite, the redeem flow offers an optional merge. Your slug and content stay on the same page id when possible; VRChat verification carries over and staff-side rules apply afterward. Accepting an invite alone creates an unlisted full page by default.

Legends list browsing and Featured remain for official Legends only. Use an invite workflow when staff want a full curated page tied to Discord.

04

Editing Your Profile

Editing requires Discord sign-in. Community profiles you created are yours to edit as soon as VRChat verification completes. Curated Legends pages must have your Discord linked by staff (invite flow); contact support@vrchatlegends.com if you need access.

How to edit

  1. 1Go to your profile page (/legends/your-id).
  2. 2Click the "Edit" button in the top-right corner.
  3. 3Sign in with Discord when prompted. You'll be redirected to Discord briefly and then sent back.
  4. 4Once signed in, click "Edit Profile" to open the editor.
  5. 5Make your changes across any of the tabs and hit Save.
  6. 6Your session lasts a few hours. Sign out when you're done if you want.

Edit modal tabs

BasicsAvatar URL, banner URL, bio, pronouns, profession, aliases/nicknames.
StoryVRChat history, life before VRChat, first steps, world creation notes, biographical info, quotes.
DetailsSpecies, gender, eye/hair color, notable for, favorite world, world list and rich world links.
Media & LinksGallery, YouTube embeds, links, and copy-ready iframe HTML for public embed endpoints (matches API docs).
VisibilityToggle which sections are publicly visible on your profile.
05

Visibility Controls

The Visibility tab in the edit modal lets you show or hide individual sections on your public profile. Your data is always saved. Hiding a section only removes it from public view. You can re-enable any section at any time.

About / Bio

Short intro at the top of your profile

Biography

Extended biographical info card

History

Life before, first steps, world creation

Quotes

Notable quotes section

Gallery

Photo gallery and lightbox

Videos

Embedded YouTube video section

Links

Social and external links sidebar

Details Sidebar

Profession, species, colors, etc.

Worlds

World links sidebar card

06

World Links

The World Links feature lets you add rich entries to your profile sidebar that show the world name, a direct VRChat link button, and an optional short description.

Name

Display name of the world (e.g. "Rainbow Library")

URL

The VRChat world URL

Description

Optional one-line blurb shown below the name

Add these in the Details tab under World Links. The older plain-text worlds field still works, but this format looks way better and is recommended for new entries.

07

Image Guidelines

All images uploaded through the site are automatically converted to WebP format for optimal compression and quality. Existing profile images hosted externally should ideally also be WebP.

Specifications

Avatar

1:1 square · min 200×200 · WebP/PNG/JPG

Banner

4:1 wide · min 1200×300 · WebP/PNG/JPG

Gallery

Any aspect · max 4 MB per image · WebP recommended

Uploading via API

Send a multipart/form-data POST to the upload endpoint with your session JWT or API key (legends:write) in the Authorization header. The server converts the image to WebP and stores it in the player's images folder, returning the hosted URL.

POST /api/players/:id/upload
Authorization: Bearer <token>
Content-Type: multipart/form-data

// field: "image" (the file to upload)
// field: "type" = "avatar" | "banner" | "gallery"
08

Community Roles

Roles are assigned via Discord and determine what permissions a member has on the site and in VRChat Legends worlds.

Owner

Full control over the site, API, Discord server, and community. Can assign all roles.

Founder

Founding member of VRChat Legends. Has the crown badge on their legend profile.

Admin

Manages community direction, can approve new legends, assign staff roles, and edit all profiles.

Staff

Core team members who moderate events, worlds, and assist with site content.

Trial Staff

Probationary staff role. Limited moderation powers while learning community standards.

Helper

Assists new members and answers questions. No moderation authority.

Representative

Represents a partner group or organization within VRChat Legends.

Developer

Technical contributor to the site. Has access to development channels and discussions.

Moderator

Enforces community rules in Discord and VRChat worlds. Can issue warnings and bans.

Contributor

Community member who contributes lore, docs, or other content. No moderation powers.

09

Getting Listed

Being added as a Legend on VRChat Legends is by invitation or community nomination. We focus on players who have made a meaningful contribution to VRChat culture, world-building, or the wider community.

There is no self-registration. If you believe you or someone else should be listed, reach out via our Discord server or at support@vrchatlegends.com.

What we look for

  • Notable contributions to the VRChat community (worlds, avatars, events, lore, etc.)
  • Active presence and positive community engagement
  • Consent from the individual to be listed
  • At least one of: founder status, verified history, or admin endorsement
10

Store

The VRChat Legends store is currently a work in progress. When it launches it will feature community merchandise and digital goods. In the meantime, our legacy shop is available.

11

API Reference

If you're a developer and want to build something with our data, here are the available endpoints. Everything returns JSON unless noted. Base URL is https://api.vrchatlegends.com.

API keys

Signed-in users can create keys in the Developer portal (max 5 keys). Send the key as Authorization: Bearer vrcl_… or X-API-Key: vrcl_…. Session JWTs from the website skip scope checks; API keys must include the scope for each action. Feed posts created with an API key are labelled with an API tag on the site.

  • account:read: Read your account (GET /api/account/me)
  • account:write: Update account profile fields
  • profile:read: Read your linked profile information
  • profile:write: Manage profile content, theme, images, and visibility
  • legends:read: Read your linked Legend profile (alias for profile:read)
  • legends:write: Update your Legend profile (alias for profile:write)
  • feed:read: Read public feed posts (profile and Social timeline)
  • feed:write: Create feed posts on your profile (tagged as API posts)
  • feed:delete: Delete your feed posts
  • comments:read: Read profile and feed comments
  • comments:write: Post, edit, delete profile and feed comments; like posts
  • followers:read: Read follower counts and follower lists
  • followers:write: Follow and unfollow profiles
  • media:write: Upload profile and feed media
  • site:read: Extended GET /api/site/context (team, products, AI guidance)
  • notifications:read: Read account notifications
  • export:read: Download personal data export ZIP

Sign in with VRChat Legends (OAuth 2.0)

Let users sign in to your app with their VRChat Legends account. Register an application in the Developer portal (up to 10 apps) to get a client ID and secret. Standard authorization-code flow with PKCE (S256) support for public clients. Users see a consent screen and approve exactly the scopes you request — you only ever get the data those scopes cover, nothing else.

  • identify: account id, display name, avatar, and the user's public Legend profile (name, bio, avatar, banner, page URL - only what is already public)
  • email: email address and whether it is verified
GET
/api/oauth2/authorize?client_id=…&redirect_uri=…&response_type=code&scope=identify&state=…
Send the user here. After consent they return to your redirect_uri with ?code and ?state.
POST
/api/oauth2/token
Exchange the code for an access token. Form or JSON body: grant_type=authorization_code, code, redirect_uri, client_id, client_secret (or code_verifier for PKCE). Also supports HTTP Basic client auth.
GET
/api/oauth2/userinfoAuth required
User data for the granted scopes. Authorization: Bearer vrclat_…
POST
/api/oauth2/revoke
Revoke an access token. Body: token, client_id, client_secret.

Codes are single-use and expire after 5 minutes; access tokens last 30 days. Redirect URIs must exactly match one registered on your application. Regenerating your client secret revokes all outstanding codes and tokens.

Common player route parameters
ParameterTypeRequiredDescription
:idstringYesLegend slug or fixed community profile ID.
sortenumNoComment order: newest, oldest, or popular.
qstringNoFull text search for feed body and VRChat photo metadata.
AuthorizationheaderNoBearer session JWT or API key when the endpoint requires authentication.

Players

GET /api/players lists curated Legends only (community profiles are excluded). Use GET /api/players/:id for any ID. Read-only HTML embed routes below work for both Legends and community IDs unless the profile is private (404).

GET
/api/players
Curated Legends list (excludes community user profiles)
GET
/api/players/featured
2 random featured legends
GET
/api/players/meAuth required
Linked player for current Discord JWT (or null)
GET
/api/players/:id
Single profile (Legends or community)
GET
/api/players/:id/embed
Embeddable profile card HTML
GET
/api/players/:id/embed-worlds
Embeddable worlds HTML
GET
/api/players/:id/embed-avatars
Embeddable avatar links HTML
GET
/api/players/:id/embed-videos
Embeddable videos HTML (community caps at 3 in player data)
GET
/api/players/:id/embed-gallery
Embeddable gallery HTML
GET
/api/players/:id/embed-comments
Embeddable read-only profile comments HTML (iframe)
GET
/api/players/:id/embed-like
Embeddable like counter HTML
GET
/api/players/:id/embed-views
Embeddable views counter HTML
GET
/api/players/:id/comments?sort=newest|oldest|popular
Nested comment tree + like counts; optional auth sets likedByMe
POST
/api/players/:id/commentsAuth required
Post thread or reply (JSON body: body, optional parentId). Session JWT or API key scope comments:write. Linked profile required.
PUT
/api/players/:id/comments/:commentIdAuth required
Edit own comment body (comments:write)
POST
/api/players/:id/comments/:commentId/likeAuth required
Toggle like on a comment (comments:write)
POST
/api/players/:id/comments/:commentId/reportAuth required
Report comment to mod Discord channel (comments:write)
DELETE
/api/players/:id/comments/:commentIdAuth required
Delete own comment, profile owner moderation, or admin (comments:write)
GET
/api/players/:id/follow-status
Whether you follow this profile + follower count; optional auth
POST
/api/players/:id/followAuth required
Follow a profile (session JWT)
DELETE
/api/players/:id/followAuth required
Unfollow a profile (session JWT)
PUT
/api/players/:idAuth required
Update own profile; community: caps on gallery/worlds/avatars/links/videos + avatar/banner hourly rate limit. API key: legends:write
POST
/api/players/:id/renameAuth required
Change display name / slug (blocked for community-owned profiles). API key: legends:write
DELETE
/api/players/:idAuth required
Delete own page where allowed. API key: legends:write
POST
/api/players/verify-vrchat/startAuth required
Start VRChat verification (blocked if community profile already exists)
POST
/api/players/verify-vrchat/checkAuth required
Finish verification; create community profile or attach VR to linked page
POST
/api/players/:id/reportAuth required
Report community profile: JSON body category + details; no self-reports
POST
/api/players/:id/report-imageAuth required
Report a specific image on a profile: JSON body imageUrl + imageType (avatar|banner|gallery|feed|comment|other) + category + optional details; no self-reports
POST
/api/players/:id/uploadAuth required
Multipart image upload (WebP); type avatar|banner|gallery|comment (comment is patron-only). All uploads are scanned for unsafe content before saving. API key: legends:write
POST
/api/players/:id/upload-fontAuth required
Upload .woff2/.woff/.ttf/.otf for profile display font. API key: legends:write

Profile feed (posts, media & comments)

Twitter-style feed for a profile. The owner must enable Feed under Edit Profile → Visibility. Media uploads accept images, gifs, and short videos (8 MB max each); VRChat in-game camera photos keep their embedded world & author metadata. Posts expose a shareUrl.

GET
/api/players/:id/feed?q=search
List feed posts (newest first) with media, comments, shareUrl, and og metadata. Optional q full-text search over body + VRChat world/author. Feed must be enabled.
GET
/api/players/:id/feed/:postId
Single feed post with og title/description/image for Discord and social embeds.
POST
/api/players/:id/feedAuth required
Create a post. JSON body: body (≤100 chars), media[] of previously uploaded feed media. Owner only. API key: legends:write. Posts made with an API key show an API tag.
DELETE
/api/players/:id/feed/:postIdAuth required
Delete a post (owner or admin). API key: legends:write
POST
/api/players/:id/upload-feed-mediaAuth required
Multipart upload one feed image/gif/video (field: media, 8 MB max). Returns url, type, width, height, and parsed vrchat metadata. Owner only. API key: legends:write
POST
/api/players/:id/feed/:postId/commentsAuth required
Comment on a post (any linked profile). JSON body: body (≤500). API key: comments:write
DELETE
/api/players/:id/feed/:postId/comments/:commentIdAuth required
Delete a feed comment (author, profile owner, or admin). API key: comments:write

String loaders (VRChat OSC / Udon)

Plain-text friendly endpoints for VRChat string loaders and automation. Append ?format=plain or send Accept: text/plain for single-line or newline output instead of JSON.

GET
/api/loaders
Index of loader endpoints
GET
/api/loaders/legends
Tab-separated name and id list of public Legends
GET
/api/loaders/legends/:playerId
Legend name + bio snippet (plain: two lines)
GET
/api/loaders/legends/:playerId/views
View count as plain number
GET
/api/loaders/legends/:playerId/likes
Like count as plain number
GET
/api/loaders/stats
Site legend/community counts + URL
GET
/api/loaders/site
Site name, tagline, URL

Site & community feeds

GET
/api/site/context
Public VRCL overview for AI assistants; extended team/products with API key scope site:read or session JWT
GET
/api/groups
VRChat groups
GET
/api/worlds
Our featured worlds
GET
/api/events
Upcoming group events
GET
/api/team
Site team members (Discord roles)
GET
/api/stats
VRChat group + Discord stats
GET
/api/discord/patreon-members
Patreon supporters via Discord

Analytics

GET
/api/analytics/legend-views
Profile view counts and top-3 leaderboard
GET
/api/analytics/legend-views/:playerId
Single legend view count
POST
/api/analytics/legend-view
Record a profile view
GET
/api/analytics/legend-likes
Profile like counts
GET
/api/analytics/legend-likes/:playerId
Single legend like count
GET
/api/analytics/history
Daily likes/views snapshots
GET
/api/analytics/online
Live visitor count
POST
/api/analytics/ping
Heartbeat to register presence

Invites

GET
/api/invite/:inviteId
Invite status
GET
/api/invite/:inviteId/auth
Discord OAuth - redeem Legends invite
POST
/api/invite/:inviteId/mergeAuth required
Merge community profile into invite (authenticated)

Auth + Config

GET
/api/auth/discord
Discord OAuth tied to invite or playerId (legacy)
GET
/api/auth/discord/callback
Discord OAuth callback
GET
/api/auth/login
Redirects to Discord OAuth (state login:…) for site JWT used by /players/me etc.
GET
/api/config
Public site configuration (nav, footer, credits)
GET
/api/health
Health check
12

Discord Bot Commands

VRChat Legends uses Discord slash commands for moderation and utility. The legacy website chat tab has been removed; use profile comments on each /legends/:id page for public discussion.

Discord Slash Commands

These are registered as Discord application commands and appear in the slash command menu.

/legends_invite_createAdministrator or Representative

Create a Legends page invite link locked to a specific Discord user. Provide either a user mention or a user ID.

/legends_vc_createAdministrator

Create a locked voice channel that displays the VRChat group member count. The channel name uses the format "Name:count" and updates automatically when site stats refresh.

Profile comments: GET /api/players/:id/comments?sort=… returns a nested tree with likes (no auth required). POST …/comments with JSON { body, parentId? } for threads or replies. Use a session JWT or an API key with comments:write. Your account must have a linked profile. PUT/DELETE …/comments/:commentId, POST …/like, and POST …/report use the same auth. Profile owners can delete comments on their page. Archived profiles cannot receive new posts.

13

Embed Snippets

Copy-paste snippets for pulling VRChat Legends data into your own projects, Discord bots, or dashboards. Html iframe targets under /api/players/:id/… are read-only and need no login. When you are signed in, copy iframe snippets from Edit Profile → Media & Links → Embed on your site (profile card, counters, worlds, gallery, profile comments, etc.) with your player id filled in automatically.

To avoid 429 rate limits, cache analytics responses and avoid rapid polling. A refresh interval of 30-60 seconds is recommended for live counters.

Profile view count

Fetch the view count for a specific legend by player ID.

js
const playerId = 'sketch494'
const res = await fetch('https://api.vrchatlegends.com/api/analytics/legend-views/' + playerId)
const { count } = await res.json()
console.log('Views:', count ?? 0)

Profile like count

Fetch the like count for a specific legend.

js
const playerId = 'sketch494'
const res = await fetch('https://api.vrchatlegends.com/api/analytics/legend-likes/' + playerId)
const { count } = await res.json()
console.log('Likes:', count ?? 0)

All views + likes combined

Fetch both in parallel and merge them.

js
const playerId = 'sketch494'
const [viewsRes, likesRes] = await Promise.all([
  fetch('https://api.vrchatlegends.com/api/analytics/legend-views/' + playerId),
  fetch('https://api.vrchatlegends.com/api/analytics/legend-likes/' + playerId),
])
const { count: viewCount } = await viewsRes.json()
const { count: likeCount } = await likesRes.json()

console.log('Views:', viewCount ?? 0)
console.log('Likes:', likeCount ?? 0)

Historical stats chart data

Fetch the daily snapshot history powering the stats chart.

js
const res = await fetch('https://api.vrchatlegends.com/api/analytics/history')
const { snapshots } = await res.json()
// snapshots = [{ date: "2025-07-01", views: { playerId: N, ... }, likes: { ... } }, ...]
const latest = snapshots.at(-1)
console.log('Snapshot for', latest?.date, ':', latest?.views)

Single-player stats endpoint

Get one legend's likes/views without pulling the full leaderboard payload.

js
const playerId = 'sketch494'
const [viewsRes, likesRes] = await Promise.all([
  fetch('https://api.vrchatlegends.com/api/analytics/legend-views/' + playerId),
  fetch('https://api.vrchatlegends.com/api/analytics/legend-likes/' + playerId),
])
const { count: viewCount } = await viewsRes.json()
const { count: likeCount } = await likesRes.json()
console.log({ playerId, viewCount, likeCount })

Core site data pulls (groups/worlds/events/team/stats)

Load the same data blocks used across VRChat Legends pages.

js
const base = 'https://api.vrchatlegends.com'
const [groups, worlds, events, team, stats] = await Promise.all([
  fetch(base + '/api/groups').then((r) => r.json()),
  fetch(base + '/api/worlds').then((r) => r.json()),
  fetch(base + '/api/events').then((r) => r.json()),
  fetch(base + '/api/team').then((r) => r.json()),
  fetch(base + '/api/stats').then((r) => r.json()),
])

console.log('groups', groups.length)
console.log('worlds', worlds.length)
console.log('events', events.length)
console.log('team', team.length)
console.log('stats', stats)

VRChat string loader (plain text)

Fetch a single number or line for OSC string loaders without parsing JSON.

js
const playerId = 'sketch494'
const views = await fetch(
  `https://api.vrchatlegends.com/api/loaders/legends/${playerId}/views?format=plain`
).then((r) => r.text())
console.log('Views:', views.trim())

Post a profile comment (API key)

Requires comments:write and a linked profile on the key's account.

js
const res = await fetch('https://api.vrchatlegends.com/api/players/sketch494/comments', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer vrcl_YOUR_KEY',
  },
  body: JSON.stringify({ body: 'Hello from my bot!' }),
})
const { comment } = await res.json()
console.log(comment.id, comment.body)

cURL quick requests

Use these to test endpoints fast from terminal.

bash
curl https://api.vrchatlegends.com/api/players
curl https://api.vrchatlegends.com/api/loaders/legends/sketch494/likes?format=plain
curl https://api.vrchatlegends.com/api/groups
curl https://api.vrchatlegends.com/api/worlds
curl https://api.vrchatlegends.com/api/events
curl https://api.vrchatlegends.com/api/team
curl https://api.vrchatlegends.com/api/stats
curl https://api.vrchatlegends.com/api/analytics/legend-views/sketch494
curl https://api.vrchatlegends.com/api/analytics/legend-likes/sketch494

Markdown badge (shields.io)

Embed a dynamic badge in a README or site. Values update daily via a cron-style fetch.

markdown
<!-- Example: link to a legend's profile page -->
[![VRChat Legends](https://img.shields.io/badge/VRChat%20Legends-View%20Profile-6B46C1?logo=vrchat&style=flat-square)](https://vrchatlegends.com/legends/sketch494)

Replace sketch494 with your profile ID: URL-safe slug for curated Legends, or your fixed community ID from /legends/<id>. Community IDs are not listed on GET /api/players but embeds still work. Private profiles return 404 from embed URLs.

Embeddable Profile Card

This profile card matches the same visual style as the embed iframe used on external sites.

Option 1: iframe embed

Drop this into any HTML page. The card renders in a self-contained iframe with transparent background.

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed"
  width="380"
  height="280"
  frameborder="0"
  style="border:none;background:transparent;border-radius:16px;overflow:hidden"
  allowtransparency="true"
  loading="lazy"
></iframe>

Option 2: JavaScript embed

Dynamically load the card into any container element.

html
<div id="vrcl-embed"></div>
<script>
  (function() {
    var playerId = 'sketch494'; // replace with any player ID
    var container = document.getElementById('vrcl-embed');
    var iframe = document.createElement('iframe');
    iframe.src = 'https://api.vrchatlegends.com/api/players/' + playerId + '/embed';
    iframe.width = '380';
    iframe.height = '280';
    iframe.style.cssText = 'border:none;background:transparent;border-radius:16px;overflow:hidden';
    iframe.setAttribute('loading', 'lazy');
    container.appendChild(iframe);
  })();
</script>

The embed card auto-updates when the legend updates their profile. It uses the same dark theme as the main site and links directly to the full profile page.

Embeddable Like Button

Shows live like count and links users to the profile page to like there.

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-like"
  width="320"
  height="44"
  frameborder="0"
  style="border:none;background:transparent;overflow:hidden"
  loading="lazy"
></iframe>

Embeddable Views Counter

Shows live profile view count and links to the profile page.

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-views"
  width="320"
  height="44"
  frameborder="0"
  style="border:none;background:transparent;overflow:hidden"
  loading="lazy"
></iframe>

Profile Content Manager Widget (Worlds, Avatar Links, Group Links, Videos, Gallery)

Drop this on your own site to let a logged-in legend update profile content arrays through the VRChat Legends API. This is a lightweight embed-style manager using your existing PUT /api/players/:id endpoint. Arrays follow the same shapes as in-site editing for world_links, avatar_links, and group_links.

html
<div id="vrcl-profile-manager"></div>
<script>
  (function () {
    const mount = document.getElementById('vrcl-profile-manager')
    if (!mount) return

    mount.innerHTML = [
      '<div style="max-width:520px;padding:16px;border:1px solid rgba(255,255,255,.12);border-radius:12px;background:#111;color:#fff;font-family:Segoe UI,system-ui,sans-serif">',
      '<h3 style="margin:0 0 10px;font-size:14px">VRCL Profile Content Manager</h3>',
      '<input id="vrcl-token" placeholder="JWT token" style="width:100%;margin:0 0 8px;padding:8px;border-radius:8px;border:1px solid #333;background:#0b0b0b;color:#fff" />',
      '<input id="vrcl-player" placeholder="playerId (example: sketch494)" style="width:100%;margin:0 0 8px;padding:8px;border-radius:8px;border:1px solid #333;background:#0b0b0b;color:#fff" />',
      '<textarea id="vrcl-world-links" rows="4" placeholder="world_links JSON array" style="width:100%;margin:0 0 8px;padding:8px;border-radius:8px;border:1px solid #333;background:#0b0b0b;color:#fff"></textarea>',
      '<textarea id="vrcl-avatar-links" rows="4" placeholder="avatar_links JSON array" style="width:100%;margin:0 0 8px;padding:8px;border-radius:8px;border:1px solid #333;background:#0b0b0b;color:#fff"></textarea>',
      '<textarea id="vrcl-group-links" rows="4" placeholder="group_links JSON array" style="width:100%;margin:0 0 8px;padding:8px;border-radius:8px;border:1px solid #333;background:#0b0b0b;color:#fff"></textarea>',
      '<textarea id="vrcl-videos" rows="3" placeholder="videos JSON array (YouTube URL strings)" style="width:100%;margin:0 0 8px;padding:8px;border-radius:8px;border:1px solid #333;background:#0b0b0b;color:#fff"></textarea>',
      '<textarea id="vrcl-gallery" rows="3" placeholder="gallery JSON array (string URLs)" style="width:100%;margin:0 0 10px;padding:8px;border-radius:8px;border:1px solid #333;background:#0b0b0b;color:#fff"></textarea>',
      '<button id="vrcl-save" style="padding:8px 12px;border:none;border-radius:8px;background:#6B46C1;color:#fff;font-weight:700;cursor:pointer">Save Profile Content</button>',
      '<pre id="vrcl-out" style="margin-top:10px;font-size:11px;white-space:pre-wrap;color:#9ca3af"></pre>',
      '</div>',
    ].join('')

    const byId = (id) => document.getElementById(id)
    byId('vrcl-save').addEventListener('click', async function () {
      const token = byId('vrcl-token').value.trim()
      const playerId = byId('vrcl-player').value.trim()
      const out = byId('vrcl-out')
      if (!token || !playerId) {
        out.textContent = 'token and playerId are required'
        return
      }

      function parseJson(id, fallback) {
        const v = byId(id).value.trim()
        if (!v) return fallback
        return JSON.parse(v)
      }

      try {
        const payload = {
          world_links: parseJson('vrcl-world-links', []),
          avatar_links: parseJson('vrcl-avatar-links', []),
          group_links: parseJson('vrcl-group-links', []),
          videos: parseJson('vrcl-videos', []),
          gallery: parseJson('vrcl-gallery', []),
        }

        const res = await fetch('https://api.vrchatlegends.com/api/players/' + encodeURIComponent(playerId), {
          method: 'PUT',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + token,
          },
          body: JSON.stringify(payload),
        })

        const data = await res.json().catch(() => ({}))
        out.textContent = JSON.stringify({ status: res.status, data }, null, 2)
      } catch (err) {
        out.textContent = String(err)
      }
    })
  })()
</script>

This manager requires a valid JWT from Discord login and updates only the signed-in user's own profile (unless admin). Treat tokens as secrets and only use this widget on trusted pages. Community (user-created) profiles enforce tighter caps via the API-for example videos arrays are limited to 3 entries, and featured world_links, avatar_links, and group_links are each limited (for example, 10 each).

Public Profile Content Embeds (No Login)

If you only want to display profile content (not edit), use these read-only embeds. No login required. Same URLs apply to community (user-created) profile IDs; the videos embed shows at most three entries for community pages.

Worlds Embed

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-worlds"
  width="420"
  height="380"
  frameborder="0"
  style="border:none;background:transparent;border-radius:12px;overflow:hidden"
  loading="lazy"
></iframe>

Avatar Links Embed

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-avatars"
  width="420"
  height="380"
  frameborder="0"
  style="border:none;background:transparent;border-radius:12px;overflow:hidden"
  loading="lazy"
></iframe>

VRChat Groups Embed

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-groups"
  width="420"
  height="380"
  frameborder="0"
  style="border:none;background:transparent;border-radius:12px;overflow:hidden"
  loading="lazy"
></iframe>

Videos Embed

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-videos"
  width="480"
  height="360"
  frameborder="0"
  style="border:none;background:transparent;border-radius:12px;overflow:hidden"
  loading="lazy"
></iframe>

Image Gallery Embed

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-gallery"
  width="420"
  height="380"
  frameborder="0"
  style="border:none;background:transparent;border-radius:12px;overflow:hidden"
  loading="lazy"
></iframe>

Profile Comments Embed

Read-only threads and replies. Visitors post on the full profile page; the embed links there.

html
<iframe
  src="https://api.vrchatlegends.com/api/players/sketch494/embed-comments"
  width="400"
  height="420"
  frameborder="0"
  style="border:none;background:transparent;border-radius:12px;overflow:hidden;max-width:100%"
  loading="lazy"
></iframe>

These embeds are public and read-only, so they can be used on external sites without sign-in. Posting comments requires sign-in or an API key with comments:write.

14

FAQ

What is a community user profile?

A separate unlisted page you can create after signing in: use /create-profile, verify your VRChat account with a code in your bio, and your page is only shared by direct link (not on the Legends list or Featured). Full Legend pages still use invites or staff listing.

How do I get my profile on the site?

Legends are added by invitation or admin approval. Reach out via Discord or email support@vrchatlegends.com.

Can I edit my own profile?

Yes! Sign in via Discord OAuth on your profile page. Your Discord account must be linked to your profile by an admin first.

What image format should I use?

WebP is preferred. Images uploaded through the edit form are automatically converted to WebP. External URLs can be any web-compatible format.

Why does the site still show content when the API is down?

The site keeps a backup copy of all data so pages always load, even if the server is having a bad day.

How do I hide a section on my profile?

Open the edit modal on your profile page, go to the Visibility tab, and toggle off any section you want to hide from public view.

How do I add worlds with clickable links?

Use the World Links section in the Details tab. Add an entry with the world name, the VRChat URL, and an optional description.

How do I add VRChat groups to my profile?

In the Details tab, use the VRChat Groups picker the same way as worlds and avatars: paste a group page URL or raw grp_ id, click Lookup, then save. You can remove entries from the list and hide the section from the Visibility tab.

How is the live visitor count calculated?

The site checks in periodically to count how many people are currently browsing. It's not exact, but it gives a good idea of activity.

Is the API public?

Most read endpoints are public. Writing (profile edits, comments, follows) requires a signed-in session or an API key with the right scope. Create keys in the Developer portal at /developers.

API Docs | VRChat Legends