1<!doctype html> 2<html lang="en"> 3<head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <!-- Google tag (gtag.js) -->
vendor: 67 bytes, lines 6-7
6 7 <script async src="https://www.googletagmanager.com/gtag/js?id=
7G-M9ES79J8K9
vendor: 15 bytes, lines 7-8
7"></script> 8
8<script> 9
vendor: 142 bytes, lines 9-12
9window.dataLayer = window.dataLayer || []; 10 function gtag(){dataLayer.push(arguments);} 11 gtag('js', new Date()); 12 gtag('config', '
12G-M9ES79J8K9
vendor: 7 bytes, lines 12-13
12'); 13
13</script>
13 14 15 <title>Threads MCP Connector for Claude â Export Posts & Followers Free</title> 16 <meta name="description" content="Ask Claude for a Threads profile's posts, followers or following. The export runs on our servers and the rows come back in the chat. Free, no card." /> 17 <meta name="keywords" content="threads mcp server, threads mcp connector, claude threads export, mcp connector claude, export threads with ai, threads data in claude, model context protocol threads" /> 18 <meta name="author" content="PostCopilot" /> 19 <meta name="application-name" content="PostCopilot MCP Connector" /> 20 <meta name="theme-color" content="#000000" /> 21 22 <!-- Favicons --> 23 <link rel="icon" type="image/x-icon" href="/favicon.ico" /> 24 <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> 25 <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> 26 <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> 27 28 <link rel="canonical" href="https://postcopilot.ai/threads-mcp-connector" /> 29 <meta name="robots" content="index,follow" /> 30 <meta name="language" content="English" /> 31 <meta name="geo.region" content="US" /> 32 33 <!-- Social preview --> 34 <meta property="og:type" content="website" /> 35 <meta property="og:site_name" content="PostCopilot" /> 36 <meta property="og:locale" content="en_US" /> 37 <meta property="og:title" content="Threads MCP Connector for Claude â Export Posts & Followers Free" /> 38 <meta property="og:description" content="Ask Claude for a Threads profile's posts or followers. We run the export. Claude shows you the rows. Free to start, nothing to install." /> 39 <meta property="og:url" content="https://postcopilot.ai/threads-mcp-connector" /> 40 <meta property="og:image" content="https://postcopilot.ai/og-cover.png" /> 41 <meta property="og:image:width" content="1200" /> 42 <meta property="og:image:height" content="630" /> 43 <meta name="twitter:card" content="summary_large_image" /> 44 <meta name="twitter:title" content="Threads MCP Connector for Claude â Export Posts & Followers Free" /> 45 <meta name="twitter:description" content="Ask Claude for a Threads profile's posts or followers. We run the export. Claude shows you the rows. Free to start, nothing to install." /> 46 <meta name="twitter:image" content="https://postcopilot.ai/og-cover.png" /> 47 48 <!-- âââ Schema.org ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 49 STATIC structured data. Every number below is a hand-written LITERAL that 50 must match the visible copy AND the server. The free numbers resolve from 51 lib/connector-tier.js freeLimits(), which itself READS config/limits.js 52 FREE (postsPerExport 20, followersPerExport 100, followingPerExport 100, 53 exportsPerDay 3, exportFileDownloadsPerDay 1 â the last one is the 54 "rows of 1 export a day" read allowance, via freeRead()). 55 56 SCOPE OF THIS PAGE (narrowed 2026-09-12): the WEBSITE connector ONLY â the 57 path where Claude asks PostCopilot's own servers to run the export, and the 58 tools that read the result. The two BROWSER-side paths (an export the 59 Chrome extension uploads into the buffer, and request_browser_export 60 queueing a job for the user's own Chrome) are deliberately not described 61 here, because the extension half of them is not shipped. They stay live on 62 the backend; the page simply stops advertising them. For the same reason 63 the Chrome extension's separate $7.99/month plan is not mentioned anywhere 64 on this page: it unlocks nothing a visitor can reach from here. Do not add 65 either back until the extension build that implements them is public. 66 67 WHAT LIFTS THE LIMITS: a WEBSITE plan â the $2 24-hour day pass or Queue 68 Pro $39.99/mo, which are the SAME entitlement with different clocks. 69 Resolved by lib/connector-entitlement.js through lib/billing.js 70 getPlan(googleSub) via isPro(), keyed on the Google account, and reached by 71 creating or linking a connector while signed in on this page. The paid 72 numbers are lib/connector-tier.js proLimits(). If any of those change, fix 73 the JSON, the plans table and the FAQ together. 74 75 The FAQPage answers below are the visible <details> answers VERBATIM (text 76 content, whitespace collapsed). Edit both or neither. --> 77
77<script type="application/ld+json"> 78 { 79 "@context": "https://schema.org", 80 "@type": "SoftwareApplication", 81 "name": "PostCopilot MCP Connector", 82 "alternateName": "Threads MCP Connector for Claude", 83 "url": "https://postcopilot.ai/threads-mcp-connector", 84 "applicationCategory": "UtilityApplication", 85 "operatingSystem": "Any MCP client (Claude and others)", 86 "description": "Get Threads posts and followers inside Claude. Ask Claude for any public Threads profile; PostCopilot's servers run the export, the rows go into a private buffer, and Claude reads and filters them in the chat. Free: 3 exports a day, up to 20 posts or 100 followers or following each, and the rows of 1 export a day (re-read it as often as you like). No credit card, nothing to install. A $2 24-hour day pass or Queue Pro at $39.99/month lifts every limit; they are the same plan with a different duration.", 87 "offers": { 88 "@type": "AggregateOffer", 89 "lowPrice": "0", 90 "highPrice": "39.99", 91 "priceCurrency": "USD", 92 "offerCount": "3", 93 "offers": [ 94 { "@type": "Offer", "name": "Free connector", "price": "0", "priceCurrency": "USD", "description": "Sign in with Google: no credit card, nothing to install. 3 exports a day per connector (5 per network), up to 20 posts or 100 followers or following each, 10 video downloads a day, and 3 exports kept for 6 hours. Claude can open the rows of 1 export a day and re-read that export as often as you like. The same allowance as the free web tools." }, 95 { "@type": "Offer", "name": "PostCopilot Queue Pro day pass", "price": "2", "priceCurrency": "USD", "description": "24 hours of the same plan as Queue Pro. Lifts every connector limit: 10 exports an hour with no daily cap, up to 2,000 rows per export, unlimited video downloads and reads, 25 exports kept for 24 hours. One payment, nothing recurring." }, 96 { "@type": "Offer", "name": "PostCopilot Queue Pro", "price": "39.99", "priceCurrency": "USD", "description": "The same plan as the day pass, by the month. Lifts every connector limit: 10 exports an hour with no daily cap, up to 2,000 rows per export, unlimited video downloads and reads, 25 exports kept for 24 hours." } 97 ] 98 }, 99 "author": { "@type": "Organization", "name": "PostCopilot", "url": "https://postcopilot.ai" } 100 } 101 </script>
101 102
102<script type="application/ld+json"> 103 { 104 "@context": "https://schema.org", 105 "@type": "FAQPage", 106 "mainEntity": [ 107 { 108 "@type": "Question", 109 "name": "How does it work?", 110 "acceptedAnswer": { 111 "@type": "Answer", 112 "text": "You ask Claude for a Threads profile. Claude calls our export tool, and the export runs on our servers. You do not need a Threads login, and nothing runs on your computer. An export takes about 20 seconds to 3 minutes. If it takes longer than about 45 seconds, Claude checks back and gets the result when it is ready. The rows go into a private buffer. Claude reads them in pages and can filter them by keyword, date, likes, follower count or verified status." 113 } 114 }, 115 { 116 "@type": "Question", 117 "name": "What do I get for free?", 118 "acceptedAnswer": { 119 "@type": "Answer", 120 "text": "3 exports a day per connector, and 5 a day per network. Each export gives up to 20 posts, or up to 100 followers or following. Claude can open the rows of 1 export a day, and re-read that export as often as you like. You also get 10 video downloads a day. This is the same allowance as our free web tools. No credit card, nothing to install." 121 } 122 }, 123 { 124 "@type": "Question", 125 "name": "Why can Claude read only one free export a day?", 126 "acceptedAnswer": { 127 "@type": "Answer", 128 "text": "Reading the rows is like downloading the file on our website, where free users get 1 file a day. Opening the same export again is free, including every page and every filter. The limit only applies to a second, different export on the same day. Listing your buffer is always free." 129 } 130 }, 131 { 132 "@type": "Question", 133 "name": "What do the $2 day pass and Queue Pro unlock?", 134 "acceptedAnswer": { 135 "@type": "Answer", 136 "text": "Every limit. You get 10 exports an hour with no daily cap, up to 2,000 rows each, unlimited video downloads and reads, and 25 exports kept for 24 hours. The $2 day pass and Queue Pro ($39.99/month) are the same plan. Only the duration is different. Buying the pass again adds time. The URL already in Claude keeps working." 137 } 138 }, 139 { 140 "@type": "Question", 141 "name": "I already have a connector token. Do I need a new one?", 142 "acceptedAnswer": { 143 "@type": "Answer", 144 "text": "No. Sign in, press Link an existing connector and paste the token (it starts with pcb_). Your plan applies within a minute. The URL in Claude and your buffer do not change." 145 } 146 }, 147 { 148 "@type": "Question", 149 "name": "Can I try it without signing in?", 150 "acceptedAnswer": { 151 "@type": "Answer", 152 "text": "Yes. In Claude, open Customize â Connectors â Add custom connector. Paste https://postcopilot.ai/mcp, leave the OAuth fields empty (if Claude asks about sign-in, choose No sign-in) and click Add. Then turn it on in a chat from the + menu â Connectors. Other MCP clients take the same URL. No token, no account. You can export a profile's posts, followers or following, download a video, and generate a Threads post. It allows 2 exports a day per IP address. Results come straight into the chat, with no private buffer and no filtering. Read the setup guide for Claude, Cursor and VS Code." 153 } 154 }, 155 { 156 "@type": "Question", 157 "name": "Which AI apps can use it?", 158 "acceptedAnswer": { 159 "@type": "Answer", 160 "text": "Any MCP client that can add a remote Streamable HTTP server. The steps above are for Claude. If your client can send an Authorization: Bearer header, use that instead of the token in the URL." 161 } 162 }, 163 { 164 "@type": "Question", 165 "name": "What happens to my data?", 166 "acceptedAnswer": { 167 "@type": "Answer", 168 "text": "Nothing is exported until you ask. There is no background sync. Exports are deleted after 6 hours on free, or 24 hours on a plan. An expired export is never shown, even before cleanup runs. You can ask Claude to delete one export or empty the whole buffer at any time. A connector can only see its own buffer. More in the privacy policy." 169 } 170 }, 171 { 172 "@type": "Question", 173 "name": "Is the connector URL a secret?",
174 "acceptedAnswer": { 175 "@type": "Answer", 176 "text": "Yes. Treat it like a password. Anyone with the URL can read that buffer, but never another account's. We store only a SHA-256 hash of it, so we show it once. Press Regenerate my connector to make the old URL stop working. Your exports stay." 177 } 178 }, 179 { 180 "@type": "Question", 181 "name": "Why is the free plan limited?", 182 "acceptedAnswer": { 183 "@type": "Answer", 184 "text": "Each export uses a real browser on our servers for 20 seconds to 3 minutes, and a shared Threads session. That is our main cost. So the free connector gets the same allowance as the free website, and a plan lifts it." 185 } 186 }, 187 { 188 "@type": "Question", 189 "name": "Which tools does Claude get?", 190 "acceptedAnswer": { 191 "@type": "Answer", 192 "text": "You never type these. Claude picks them from your request. export_posts, export_followers, export_following: run a new export on our servers. get_job: checks an export that is still running. download_video: returns direct video and photo links for one post. Works with /share/ links. list_exports: shows what is in your buffer and when it expires. get_export: reads an export in pages (50 by default, up to 500). query_export: filters and sorts rows without loading all of them. delete_export: deletes one export. purge_buffer: deletes everything, after you confirm." 193 } 194 } 195 ] 196 } 197 </script>
197 198
198<script type="application/ld+json"> 199 { 200 "@context": "https://schema.org", 201 "@type": "BreadcrumbList", 202 "itemListElement": [ 203 { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://postcopilot.ai/" }, 204 { "@type": "ListItem", "position": 2, "name": "Threads MCP Connector", "item": "https://postcopilot.ai/threads-mcp-connector" } 205 ] 206 } 207 </script>
207 208 209 <link rel="stylesheet" href="/styles.css?v=20260914"> 210 <style> 211 /* Calm layout: plain sections separated by whitespace. The connector card 212 (#connect-plan) is the ONLY raised surface, because it holds the one 213 action the page exists for. */ 214 #connect-plan, #plans, #faq, #faq-no-signin { scroll-margin-top: 84px; } 215 .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; } 216 217 .cta:focus-visible, .cta-secondary:focus-visible, .text-link:focus-visible, 218 details summary:focus-visible, .tools-grid a:focus-visible { 219 outline: 2px solid var(--primary); outline-offset: 3px; 220 } 221 222 /* ââ Hero ââ */ 223 .c-hero { margin-bottom: 0; padding: 24px 0 8px; } 224 .c-hero h1 { max-width: 640px; margin-left: auto; margin-right: auto; } 225 .c-hero .lead { max-width: 560px; } 226 .c-hero__cta { margin-top: 28px; } 227 .c-hero__cta .cta { width: auto; min-width: 300px; text-decoration: none; } 228 /* --text-secondary, not --text-muted: #a3a3a3 on #ffffff is ~2.5:1 (fails AA). */ 229 .micro { margin: 12px 0 0; font-size: 14px; color: var(--text-secondary); } 230 .text-link { 231 display: inline-flex; align-items: center; min-height: 44px; margin-top: 4px; 232 font-size: 15px; font-weight: 600; color: var(--text); 233 text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--border); 234 } 235 .text-link:hover { text-decoration-color: currentColor; } 236 237 /* ââ Section rhythm ââ */ 238 .sec { margin-top: 72px; } 239 .sec h2 { margin: 0 0 8px; font-size: clamp(22px, 4vw, 28px); font-weight: 700; letter-spacing: -0.02em; color: var(--text); } 240 .sec__intro { margin: 0; font-size: 16px; line-height: 1.6; color: var(--text-secondary); max-width: 640px; } 241 .fine { margin: 14px 0 0; font-size: 14px; line-height: 1.6; color: var(--text-secondary); } 242 .fine strong { color: var(--text); font-weight: 600; } 243 244 /* ââ Examples as a chat ââ */ 245 .chat { display: grid; gap: 16px; margin-top: 24px; } 246 .ex { 247 background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-lg); 248 padding: 20px; 249 } 250 .ex__who { 251 display: block; margin-bottom: 6px; font-size: 12px; font-weight: 700; 252 letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-secondary); 253 } 254 .ex__ask { 255 margin: 0 0 16px; padding: 12px 16px; 256 background: var(--surface); border: 1px solid var(--border); 257 border-radius: var(--radius-lg) var(--radius-lg) 4px var(--radius-lg); 258 font-size: 15px; line-height: 1.5; color: var(--text); 259 } 260 .ex__ask:last-child { margin-bottom: 0; } 261 .ex__answer { font-size: 14px; color: var(--text-secondary); } 262 .ex__answer p { margin: 0; line-height: 1.55; } 263 .mini-wrap { overflow-x: auto; } 264 .mini-table { width: 100%; border-collapse: collapse; font-size: 14px; font-variant-numeric: tabular-nums; } 265 .mini-table caption { text-align: left; padding-bottom: 8px; font-size: 13px; font-style: italic; color: var(--text-secondary); } 266 .mini-table th, .mini-table td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; } 267 .mini-table thead th { font-size: 12px; font-weight: 600; color: var(--text-secondary); } 268 .mini-table tbody td { color: var(--text); } 269 .mini-table tbody tr:last-child td { border-bottom: 0; } 270 .mini-table .num { text-align: right; white-space: nowrap; } 271 .mini-table .nowrap { white-space: nowrap; } 272 273 code { 274 font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; 275 font-size: 0.92em; padding: 1px 5px; border-radius: 5px; 276 background: var(--surface-2); border: 1px solid var(--border); 277 } 278 279 /* ââ The one raised surface: create a connector ââ */ 280 .card { 281 background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); 282 padding: 32px; box-shadow: var(--shadow-lg); 283 } 284 .steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 24px 0 0; padding: 0; list-style: none; } 285 .step { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; } 286 .step__num { 287 display: inline-flex; align-items: center; justify-content: center; 288 width: 28px; height: 28px; border-radius: 50%; margin-bottom: 10px; 289 background: linear-gradient(135deg, var(--primary), var(--secondary)); 290 color: var(--on-primary); font-size: 14px; font-weight: 700; 291 } 292 .step h3 { margin: 0 0 6px; font-size: 16px; font-weight: 700; color: var(--text); } 293 .step p { margin: 0; font-size: 14px; color: var(--text-secondary); line-height: 1.55; } 294 295 .url-block { 296 margin: 16px 0 0; padding: 14px 16px; overflow-x: auto; 297 background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius); 298 font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; 299 font-size: 14px; color: var(--text); white-space: nowrap; 300 } 301 .url-block .tok { color: var(--text-secondary); } 302 303 /* Shared by the authored markup AND the strings #connect-plan's script 304 renders (hero-ctas, plans-fine, facts) â keep these class names. */ 305 .hero-ctas { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; } 306 .hero-ctas .cta { width: auto; min-width: 260px; text-decoration: none; } 307 .hero-ctas .cta-secondary { text-decoration: none; } 308 .plans-fine { margin-top: 14px; font-size: 14px; line-height: 1.6; color: var(--text-secondary); } 309 .plans-fine strong { color: var(--text); font-weight: 600; } 310 .facts { margin: 16px 0 0; padding-left: 20px; color: var(--text-secondary); line-height: 1.8; font-size: 15px; } 311 .connect-panel { margin-top: 24px; } 312 .connect-panel > .hero-ctas { justify-content: flex-start; } 313 314 /* ââ Plans table ââ */ 315 .plans-table { width: 100%; border-collapse: collapse; font-size: 15px; margin-top: 24px; } 316 .plans-table th, .plans-table td { padding: 14px 12px; text-align: left; border-bottom: 1px solid var(--border); } 317 .plans-table thead th { 318 font-size: 13px; font-weight: 600; color: var(--text-secondary); border-bottom: 2px solid var(--border); 319 } 320 /* TWO value columns. The label column takes the spare width rather than the 321 values stretching: a comparison reads wrong the moment one side is visibly 322 roomier than the other. */ 323 .plans-table thead th:first-child { width: 34%; } 324 .plans-table tbody th { font-weight: 600; color: var(--text); } 325 .plans-table td { color: var(--text-secondary); } 326 .plans-table .pro-col { background: var(--surface-2); color: var(--text); font-weight: 600; }
327 /* Column caption rendered INSIDE each cell for the linearised mobile layout. 328 A real element, not a ::before â generated content is not reliably exposed 329 to screen readers, and once the table is display:block the native header 330 association is gone, so this is the only thing left saying which plan a 331 value belongs to. Hidden on desktop, where the real <th> does the job. */ 332 .cell-plan { display: none; } 333 .buy-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 20px; } 334 .buy-row .cta { width: auto; min-width: 240px; } 335 .buy-row .cta-secondary { text-decoration: none; } 336 337 /* ââ FAQ ââ */ 338 .faq-list { margin-top: 24px; } 339 details > .faq-a { padding: 0 16px 16px; color: var(--text-secondary); font-size: 15px; line-height: 1.65; } 340 .faq-a p { margin: 0 0 10px; } 341 .faq-a p:last-child { margin-bottom: 0; } 342 .faq-a ul { margin: 0; padding-left: 20px; } 343 .faq-a li { margin-bottom: 6px; } 344 345 /* ââ Closing CTA ââ */ 346 .final-cta { text-align: center; padding: 48px 24px; border-radius: var(--radius-lg); background: var(--surface-2); border: 1px solid var(--border); } 347 .final-cta .sec__intro { margin: 0 auto; } 348 .final-cta .cta { width: auto; min-width: 300px; margin-top: 24px; text-decoration: none; } 349 350 /* ââ More tools: kept for internal linking, deliberately quiet ââ */ 351 .more-tools { margin-top: 64px; padding-top: 32px; border-top: 1px solid var(--border); } 352 .more-tools h2 { margin: 0; font-size: 17px; font-weight: 600; color: var(--text-secondary); } 353 .more-tools .tools-grid { margin-top: 16px; gap: 10px; } 354 .more-tools .tools-grid a { background: transparent; } 355 .more-tools .tools-grid a:hover { transform: none; box-shadow: none; } 356 357 /* ââ Responsive ââ */ 358 @media (max-width: 800px) { 359 .steps { grid-template-columns: 1fr; } 360 } 361 @media (max-width: 640px) { 362 .sec { margin-top: 56px; } 363 .card { padding: 24px 18px; } 364 .ex { padding: 14px; } 365 .ex__ask { font-size: 14.5px; } 366 .mini-table { font-size: 13px; } 367 .mini-table th, .mini-table td { padding: 8px 6px; } 368 /* Example data only: at 360px four columns squeeze the post text to a 369 sliver, so the least useful column drops out. */ 370 .mini-table .col-opt { display: none; } 371 .c-hero__cta .cta, .final-cta .cta, .buy-row .cta, .buy-row .cta-secondary, 372 .hero-ctas .cta, .hero-ctas .cta-secondary { width: 100%; min-width: 0; } 373 .final-cta { padding: 32px 18px; } 374 /* At 360px the connector URL is wider than the viewport. Wrap it rather 375 than scroll it: a URL people are told to COPY must be fully visible. */ 376 .url-block { font-size: 12.5px; white-space: normal; overflow-wrap: anywhere; word-break: break-all; } 377 378 /* A 360px table leaves ~110px per value column, not enough for "10 an 379 hour, no daily cap". Linearise row-major instead: each row becomes a 380 block headed by its label, values stacked beneath with their own 381 caption. Horizontal scroll was rejected â you cannot compare a column 382 that is off-screen. */ 383 .plans-table, .plans-table tbody, .plans-table tr, 384 .plans-table th, .plans-table td { display: block; width: auto; } 385 .plans-table thead { display: none; } 386 .plans-table { font-size: 14px; margin-top: 16px; } 387 .plans-table tbody tr { padding: 14px 0 4px; border-bottom: 1px solid var(--border); } 388 .plans-table tbody tr:last-child { border-bottom: 0; } 389 .plans-table tbody th[scope="row"] { padding: 0 0 8px; border-bottom: 0; } 390 .plans-table tbody td { 391 display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 10px; 392 align-items: baseline; padding: 5px 10px 5px 13px; border-bottom: 0; 393 } 394 .plans-table tbody td.pro-col { border-left: 3px solid var(--success); border-radius: 8px; } 395 .cell-plan { display: block; font-size: 12px; font-weight: 600; color: var(--text-secondary); } 396 } 397 398 @media (prefers-reduced-motion: reduce) { 399 .cta, .cta-secondary, .tools-grid a { transition: none; } 400 .cta:hover { transform: none; } 401 } 402 </style> 403</head> 404<body> 405 <div id="header-placeholder"></div> 406 <div class="wrap"> 407 408 <!-- ââ HERO âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 409 One headline, one sentence, one button. The button goes STRAIGHT to 410 Google sign-in (not to a section that shows the same button). Sign-in 411 cannot return to a #hash â /auth/google/callback appends "?auth=ok" to 412 returnTo, which would land after the fragment â so the page script 413 scrolls to #connect-plan when it sees auth=ok instead. When the status 414 call says the visitor is already signed in, the script relabels both 415 .js-connector-cta buttons "Create my connector" and points them at 416 #connect-plan;
416 their gtag event name comes from data-event. --> 417 <header class="c-hero"> 418 <h1>Get any Threads profile's posts, followers and following inside Claude</h1> 419 <p class="lead">Ask Claude for any public Threads profile. Our servers run the export, and the rows come back in the chat.</p> 420 <div class="c-hero__cta"> 421 <a class="cta js-connector-cta" href="/auth/google?return=/threads-mcp-connector" data-event="click_connector_signin" data-placement="hero" onclick="if(typeof gtag==='function')gtag('event',this.getAttribute('data-event'),{placement:'hero'})">Sign in with Google — it's free</a> 422 <p class="micro">No credit card. Nothing to install. 3 free exports a day.</p> 423 <a class="text-link" href="#faq-no-signin" onclick="if(typeof gtag==='function')gtag('event','click_connector_try_public',{placement:'hero'})">Or try it without signing in</a> 424 </div> 425 </header> 426 427 <!-- ââ EXAMPLES âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 428 Every handle and number here is MADE UP, and says so. Column names match 429 the real fields (posts: text, likes, replies, reposts, postedAt; people: 430 username, full_name, follower_count, is_verified). Example 1 asks for 20 431 posts and example 2 fits inside 100 followers ON PURPOSE, so both run on 432 a free connector â do not raise them. --> 433 <section class="sec" aria-labelledby="examples-h"> 434 <h2 id="examples-h">Paste this into Claude</h2> 435 <p class="sec__intro">You write a normal request. Claude picks the tools, runs the export and answers.</p> 436 437 <div class="chat"> 438 <div class="ex"> 439 <p class="ex__ask"><span class="ex__who">You</span>Export the last 20 posts from @coffee.lab and show me the 3 with the most replies.</p> 440 <div class="ex__answer mini-wrap"> 441 <table class="mini-table"> 442 <caption>What Claude shows you (example data)</caption> 443 <thead><tr><th scope="col" class="col-opt">Posted</th><th scope="col">Post</th><th scope="col" class="num">Likes</th><th scope="col" class="num">Replies</th></tr></thead> 444 <tbody> 445 <tr><td class="col-opt nowrap">Sep 9</td><td>“Oat milk or whole milk for a flat white?”</td><td class="num">412</td><td class="num">188</td></tr> 446 <tr><td class="col-opt nowrap">Sep 4</td><td>“We are closing early on Friday. Here's why…”</td><td class="num">530</td><td class="num">97</td></tr> 447 <tr><td class="col-opt nowrap">Aug 30</td><td>“New beans from Kenya this week.”</td><td class="num">301</td><td class="num">64</td></tr> 448 </tbody> 449 </table> 450 </div> 451 </div> 452 453 <div class="ex"> 454 <p class="ex__ask"><span class="ex__who">You</span>Export @coffee.lab's followers. List the verified ones with more than 10,000 followers.</p> 455 <div class="ex__answer mini-wrap"> 456 <table class="mini-table"> 457 <caption>What Claude shows you (example data)</caption> 458 <thead><tr><th scope="col">Username</th><th scope="col" class="col-opt">Name</th><th scope="col" class="num">Followers</th><th scope="col">Verified</th></tr></thead> 459 <tbody> 460 <tr><td>@citybites</td><td class="col-opt">City Bites</td><td class="num">48,200</td><td>Yes</td></tr> 461 <tr><td>@brewdaily</td><td class="col-opt">Brew Daily</td><td class="num">21,050</td><td>Yes</td></tr> 462 </tbody> 463 </table> 464 </div> 465 </div> 466 467 <div class="ex"> 468 <p class="ex__ask"><span class="ex__who">You</span>Download the video from this Threads link: threads.com/@coffee.lab/post/…</p> 469 <div class="ex__answer"><p>Claude returns the direct video and photo links, with no watermark.</p></div> 470 </div> 471 </div> 472 473 <p class="fine">The rows stay in a private buffer. Claude can filter them again without a new exp
473ort. <strong>Free: open the rows of 1 export a day</strong> (re-read it as often as you like).</p> 474 </section> 475 476 <!-- ââ THE DOOR ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 477 The page's one entry point, and its primary conversion action: sign in 478 here, mint a connector, paste it into Claude. It is also where a WEBSITE 479 plan gets tied to a connector, because a plan is keyed on a Google 480 account (lib/billing.js billing_plans/{googleSub}) and the token has to 481 be attached to one â which can only happen while the user is signed in 482 HERE, where the sub is proven by the OAuth session rather than typed. 483 484 Everything below is progressive enhancement: with JS off, or before the 485 status call returns, it is still a readable, correctly-priced 486 explanation plus a working Sign in with Google link. --> 487 <section class="sec card" id="connect-plan" aria-labelledby="connect-h"> 488 <h2 id="connect-h">Set it up in about a minute</h2> 489 <ol class="steps"> 490 <li class="step"> 491 <div class="step__num" aria-hidden="true">1</div> 492 <h3>Sign in with Google</h3> 493 <p>Free. No card, no email to confirm.</p> 494 </li> 495 <li class="step"> 496 <div class="step__num" aria-hidden="true">2</div> 497 <h3>Press Create my connector</h3> 498 <p>You get a private URL. It is shown once, so copy it.</p> 499 </li> 500 <li class="step"> 501 <div class="step__num" aria-hidden="true">3</div> 502 <h3>Paste it into Claude</h3> 503 <p>Customize → Connectors → Add custom connector. Paste the URL. Done.</p> 504 </li> 505 </ol> 506 <p class="url-block">https://postcopilot.ai/mcp/connector/<span class="tok"><your-token></span></p> 507 <div id="connectPlanState" class="connect-panel" aria-live="polite"> 508 <div class="hero-ctas" id="connectPlanSignedOut"> 509 <a class="cta" href="/auth/google?return=/threads-mcp-connector" onclick="if(typeof gtag==='function')gtag('event','click_connector_signin',{placement:'connect_plan'})">Sign in with Google</a> 510 </div> 511 </div> 512 <p class="fine">Keep this URL private, like a password. Lost it? Press <em>Regenerate my connector</em> and the old one stops working.</p> 513 </section> 514 515 <section class="sec" id="plans" aria-labelledby="plans-h"> 516 <h2 id="plans-h">Free to start. $2 when you need more.</h2> 517 <p class="sec__intro">The free connector gives the same allowance as our free web tools.</p> 518 <!-- Every literal in this table is a number the SERVER enforces. 519 FREE: lib/connector-tier.js freeLimits(), which reads config/limits.js 520 FREE (20 / 100 / 100 / 3 / 1 â the 1 is freeRead(): the rows of one 521 server-scraped export per UTC day, re-reads of it free); buffer depth 522 and TTL â CONNECTOR_FREE_MAX_EXPORTS_PER_ACCOUNT 3, 523 CONNECTOR_FREE_TTL_HOURS 6; per-network cap â 524 CONNECTOR_FREE_EXPORTS_PER_DAY_PER_IP 5; video â 525 CONNECTOR_FREE_VIDEOS_PER_DAY 10. 526 527 ON A PLAN ($2 day pass or Queue Pro $39.99/mo â the SAME entitlement, 528 only the duration differs): proLimits() â exportsPerHour 10, 529 exportMaxItems 2000, exportReadsPerDay 0 and videosPerDay 0 (both 530 meaning "not metered"), maxExportsPerAccount 25, ttlHours 24. --> 531 <table class="plans-table"> 532 <thead> 533 <tr> 534 <th scope="col"><span class="sr-only">Limit</span></th> 535 <th scope="col">Free</th> 536 <th scope="col">$2 day pass or Queue Pro</th> 537 </tr> 538 </thead> 539 <tbody> 540 <tr> 541 <th scope="row">Exports</th> 542 <td><span class="cell-plan">Free</span>3 a day (5 per network)</td> 543 <td class="pro-col"><span class="cell-plan">On a plan</span>10 an hour, no daily cap</td> 544 </tr> 545 <tr> 546 <th scope="row">Rows per export</th> 547 <td><span class="cell-plan">Free</span>20 posts, or 100 followers or following</td> 548 <td class="pro-col"><span class="cell-plan">On a plan</span>Up to 2,000</td> 549 </tr> 550 <tr> 551 <th scope="row">Video downloads</th> 552 <td><span class="cell-plan">Free</span>10 a day</td> 553 <td class="pro-col"><span class="cell-plan">On a plan</span>No daily cap</td> 554 </tr> 555 <tr> 556 <th scope="row">Reading rows back</th> 557 <td><span class="cell-plan">Free</span>1 export a day, re-reads free</td> 558 <td class="pro-col"><span class="cell-plan">On a plan</span>Unlimited</td> 559 </tr> 560 <tr> 561 <th scope="row">Kept in buffer</th> 562 <td><span class="cell-plan">Free</span>3 exports, 6 hours</td> 563 <td class="pro-col"><span class="cell-plan">On a plan</span>25 exports, 24 hours</td> 564 </tr> 565 </tbody> 566 </table> 567 <p class="fine">The $2 day pass and Queue Pro are the <strong>same plan</strong>. The pass lasts 24 hours. Queue Pro is $39.99/month. The connector URL in Claude keeps working after you buy.</p> 568 <div class="buy-row"> 569 <button class="cta" type="button" data-pc-buy-day-pass data-
569pc-surface="connector_plans">Get 24 hours for $2</button> 570 <a class="cta-secondary" href="/bulk-threads-downloader" data-pc-buy data-pc-surface="connector_plans_monthly">Queue Pro — $39.99/month</a> 571 </div> 572 </section> 573 574 <section class="sec" id="faq" aria-labelledby="faq-h"> 575 <h2 id="faq-h">Questions</h2> 576 <!-- Deliberately NO tool COUNT anywhere in the tools answer. A count is the 577 one claim on this page that goes stale on a deploy rather than on a 578 decision â the tool list in mcp/connector-server.mjs changes â and a 579 page that says "nine" beside a connector offering ten is wrong for no 580 benefit. --> 581 <div class="faq-list"> 582 <details> 583 <summary>How does it work?</summary> 584 <div class="faq-a"><p>You ask Claude for a Threads profile. Claude calls our export tool, and the export runs on our servers. You do not need a Threads login, and nothing runs on your computer. An export takes about 20 seconds to 3 minutes. If it takes longer than about 45 seconds, Claude checks back and gets the result when it is ready. The rows go into a private buffer. Claude reads them in pages and can filter them by keyword, date, likes, follower count or verified status.</p></div> 585 </details> 586 <details> 587 <summary>What do I get for free?</summary> 588 <div class="faq-a"><p>3 exports a day per connector, and 5 a day per network. Each export gives up to 20 posts, or up to 100 followers or following. Claude can open the rows of 1 export a day, and re-read that export as often as you like. You also get 10 video downloads a day. This is the same allowance as our free web tools. No credit card, nothing to install.</p></div> 589 </details> 590 <details> 591 <summary>Why can Claude read only one free export a day?</summary> 592 <div class="faq-a"><p>Reading the rows is like downloading the file on our website, where free users get 1 file a day. Opening the same export again is free, including every page and every filter. The limit only applies to a second, different export on the same day. Listing your buffer is always free.</p></div> 593 </details> 594 <details> 595 <summary>What do the $2 day pass and Queue Pro unlock?</summary> 596 <div class="faq-a"><p>Every limit. You get 10 exports an hour with no daily cap, up to 2,000 rows each, unlimited video downloads and reads, and 25 exports kept for 24 hours. The $2 day pass and <a href="/bulk-threads-downloader">Queue Pro</a> ($39.99/month) are the same plan. Only the duration is different. Buying the pass again adds time. The URL already in Claude keeps working.</p></div> 597 </details> 598 <details> 599 <summary>I already have a connector token. Do I need a new one?</summary> 600 <div class="faq-a"><p>No. Sign in, press <em>Link an existing connector</em> and paste the token (it starts with <code>pcb_</code>). Your plan applies within a minute. The URL in Claude and your buffer do not change.</p></div> 601 </details> 602 <details id="faq-no-signin"> 603 <summary>Can I try it without signing in?</summary> 604 <div class="faq-a"><p>Yes. In Claude, open Customize → Connectors → Add custom connector. Paste <code>https://postcopilot.ai/mcp</code>, leave the OAuth fields empty (if Claude asks about sign-in, choose <em>No sign-in</em>) and click Add. Then turn it on in a chat from the + menu → Connectors. Other MCP clients take the same URL. No token, no account. You can export a profile's posts, followers or following, download a video, and generate a Threads post. It allows 2 exports a day per IP address. Results come straight into the chat, with no private buffer and no filtering. Read the <a href="/blog/postcopilot-mcp-server-threads-ai-tools">setup guide for Claude, Cursor and VS Code</a>.</p></div> 605 </details> 606 <details> 607 <summary>Which AI apps can use it?</summary> 608 <div class="faq-a"><p>Any MCP client that can add a remote Streamable HTTP server. The steps above are for Claude. If your client can send an <code>Authorization: Bearer</code> header, use that instead of the token in the URL.</p></div> 609 </details> 610 <details> 611 <summary>What happens to my data?</summary> 612 <div class="faq-a"><p>Nothing is exported until you ask. There is no background sync. E
612xports are deleted after 6 hours on free, or 24 hours on a plan. An expired export is never shown, even before cleanup runs. You can ask Claude to delete one export or empty the whole buffer at any time. A connector can only see its own buffer. More in the <a href="/privacy">privacy policy</a>.</p></div> 613 </details> 614 <details> 615 <summary>Is the connector URL a secret?</summary> 616 <div class="faq-a"><p>Yes. Treat it like a password. Anyone with the URL can read that buffer, but never another account's. We store only a SHA-256 hash of it, so we show it once. Press <em>Regenerate my connector</em> to make the old URL stop working. Your exports stay.</p></div> 617 </details> 618 <details> 619 <summary>Why is the free plan limited?</summary> 620 <div class="faq-a"><p>Each export uses a real browser on our servers for 20 seconds to 3 minutes, and a shared Threads session. That is our main cost. So the free connector gets the same allowance as the free website, and a plan lifts it.</p></div> 621 </details> 622 <details> 623 <summary>Which tools does Claude get?</summary> 624 <div class="faq-a"> 625 <p>You never type these. Claude picks them from your request.</p> 626 <ul> 627 <li><code>export_posts</code>, <code>export_followers</code>, <code>export_following</code>: run a new export on our servers.</li> 628 <li><code>get_job</code>: checks an export that is still running.</li> 629 <li><code>download_video</code>: returns direct video and photo links for one post. Works with <code>/share/</code> links.</li> 630 <li><code>list_exports</code>: shows what is in your buffer and when it expires.</li> 631 <li><code>get_export</code>: reads an export in pages (50 by default, up to 500).</li> 632 <li><code>query_export</code>: filters and sorts rows without loading all of them.</li> 633 <li><code>delete_export</code>: deletes one export.</li> 634 <li><code>purge_buffer</code>: deletes everything, after you confirm.</li> 635 </ul> 636 </div> 637 </details> 638 </div> 639 </section> 640
641 <section class="sec final-cta" aria-labelledby="final-h"> 642 <h2 id="final-h">Try it with your first profile</h2> 643 <p class="sec__intro">Sign in, copy one URL, paste it into Claude. 3 free exports a day, no card.</p> 644 <a class="cta js-connector-cta" href="/auth/google?return=/threads-mcp-connector" data-event="click_connector_signin" data-placement="footer" onclick="if(typeof gtag==='function')gtag('event',this.getAttribute('data-event'),{placement:'footer'})">Sign in with Google — it's free</a> 645 <div><a class="text-link" href="#plans">See plans</a></div> 646 </section> 647 648 <section class="more-tools" aria-labelledby="more-h"> 649 <h2 id="more-h">More Free Threads Tools</h2> 650 <div class="tools-grid"> 651 <a href="/post-downloader"><h3>Threads Post Downloader</h3><p>Download any profile's posts as CSV or JSON â free, no signup</p></a> 652 <a href="/threads-follower-export"><h3>Threads Follower Export</h3><p>Export followers and following lists from any Threads profile to CSV</p></a> 653 <a href="/download"><h3>Threads Video Downloader</h3><p>Save Threads videos and photos in MP4 or JPG â no watermark, no signup</p></a> 654 <a href="/bulk-threads-downloader"><h3>Bulk Threads Downloader</h3><p>Queue a list of @handles and get every profile's files by email</p></a> 655 <a href="/threads-exporter-extension"><h3>Threads Exporter Extension</h3><p>Chrome extension to export followers & posts directly from Threads</p></a> 656 </div> 657 </section> 658 659 <div id="footer-placeholder"></div> 660 </div> 661 662
662<script src="/components/loader.js?v=20260711"></script>
662 663 664 <!-- ââ #connect-plan behaviour ââââââââââââââââââââââââââââââââââââââââââââ 665 Mints a connector for the signed-in PostCopilot account, and ties an 666 existing one to it so a WEBSITE plan ($2 day pass / Queue Pro) applies. 667 Nothing here computes a limit or a price: every number and every sentence 668 it renders comes from /api/connector/web/status and 669 /api/connector/web/token, i.e. from the same entitlement the server 670 enforces one function call later. That rule exists because of the 671 /post-downloader incident, where the page advertised the 10/day shared 672 shield while the server enforced a 3/day quota. 673 674 Progressive enhancement and fail-silent throughout: signed out, or with 675 this script blocked, the section is still a readable explanation plus a 676 working Sign in with Google link. A network error never leaves the panel 677 in a spinner â it says what happened and offers the action again. --> 678
678<script> 679 (function () { 680 'use strict'; 681 var box = document.getElementById('connectPlanState'); 682 if (!box) return; 683 684 function esc(v) { 685 return String(v == null ? '' : v).replace(/[&<>"']/g, function (c) { 686 return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; 687 }); 688 } 689 function track(name, params) { 690 try { if (typeof gtag === 'function') gtag('event', name, params || {}); } catch (_) {} 691 } 692 async function api(method, url, body) { 693 var res = await fetch(url, { 694 method: method, 695 // Same-origin only, and credentials are required: these are the ONE 696 // family of connector routes authenticated by the pc_session cookie. 697 credentials: 'same-origin', 698 headers: body ? { 'Content-Type': 'application/json' } : undefined, 699 body: body ? JSON.stringify(body) : undefined 700 }); 701 var json = null; 702 try { json = await res.json(); } catch (_) {} 703 return { status: res.status, json: json || {} }; 704 } 705 706 // The plan line. Server-authored where a limit is involved; the labels here 707 // are only names for a plan the server already told us we hold. 708 function planLine(st) { 709 if (!st.webPro) { 710 return '<strong>No plan on this account.</strong> This connector runs on the free allowance ' + 711 '— 3 exports and 10 video downloads a day. A $2 24-hour day pass ' + 712 'or Queue Pro ($39.99/month) lifts them.'; 713 } 714 if (st.dayPass && st.planEndsAt) { 715 return '<strong>Day pass active</strong> until ' + esc(new Date(st.planEndsAt).toLocaleString()) + 716 '. Exports and video downloads are unmetered on this connector.'; 717 } 718 if (st.planStatus === 'canceling' && st.planEndsAt) { 719 return '<strong>Queue Pro</strong>, ending ' + esc(new Date(st.planEndsAt).toLocaleDateString()) + 720 '. Exports and video downloads are unmetered on this connector.'; 721 } 722 return '<strong>Queue Pro active.</strong> Exports and video downloads are unmetered on this connector.'; 723 } 724 725 function render(st) { 726 // `origin` is the server's own provenance field. Anything not minted here 727 // is labelled neutrally as "Linked" â this page does not describe where 728 // else a token could have come from, and inventing a source in a label 729 // would be the page advertising a path again. 730 var connectors = st.connectors || []; 731 var rows = connectors.map(function (c) { 732 return '<li>' + esc(c.origin === 'web' ? 'Created here' : 'Linked') + 733 (c.label ? ' · ' + esc(c.label) : '') + 734 (c.lastUsedAt ? ' · last used ' + esc(new Date(c.lastUsedAt).toLocaleDateString()) : '') + 735 '</li>'; 736 }).join(''); 737 738 // Only a web-origin connector is replaced by POST /api/connector/web/token â 739 // mintWebToken() skips any doc whose origin !== 'web'. Gating on `rows` (ANY 740 // connector, including linked extension ones) told people with only a linked 741 // connector that it would "stop working immediately", which is false: nothing 742 // was revoked, and they silently ended up with a SECOND connector on a second, 743 // empty-looking buffer. Gate on the thing the server actually rotates. 744 var hasWebConnector = connectors.some(function (c) { return c.origin === 'web'; }); 745 746 box.innerHTML = 747 '<p class="plans-fine">Signed in as <strong>' + esc(st.email) + '</strong>. ' + planLine(st) + '</p>' + 748 (rows ? '<ul class="facts" style="margin-top:12px;">' + rows + '</ul>' : '') + 749 '<div class="hero-ctas" style="margin-top:16px;">' + 750 '<button class="cta" type="button" id="cpCreate">' + 751 (hasWebConnector ? 'Regenerate my connector' : 'Create my connector') + '</button>' + 752 '<button class="cta-secondary" type="button" id="cpLinkOpen">Link an existing connector</button>' + 753 '</div>' + 754 '<div id="cpOut"></div>'; 755 756 var create = document.getElementById('cpCreate'); 757 if (create) { 758 create.addEventListener('click', function () { 759 var regenerate = hasWebConnector; 760 if (regenerate && !window.confirm( 761 'This creates a new connector URL and makes the one you created here stop working ' + 762 'immediately. Any connector you linked from the extension is not affected. ' + 763 'Your buffered exports are kept. Continue?')) return; 764 create.disabled = true; 765 create.textContent = 'Creatingâ¦'; 766 track('connector_web_token', { regenerate: regenerate }); 767 api('POST', '/api/connector/web/token', {}).then(function (r) { 768 create.disabled = false; 769 create.textContent = regenerate ? 'Regenerate my connector' : 'Create my connector'; 770 var out = document.getElementById('cpOut'); 771 if (r.status !== 200 || !r.json.token) { 772 out.innerHTML = '<p class="plans-fine">
772' + 773 esc(r.json.error || 'Could not create a connector. Try again in a moment.') + '</p>'; 774 return; 775 } 776 // Shown ONCE. The server stores only a SHA-256 of it, so there is no 777 // way to show it again later â said out loud rather than discovered. 778 out.innerHTML = 779 '<p class="plans-fine" style="margin-top:18px;"><strong>Paste this into Claude</strong> ' + 780 '(Customize → Connectors → Add custom connector). It is shown once and cannot be ' + 781 'recovered — we only ever store a hash of it. Treat it like a password.</p>' + 782 '<p class="url-block">' + esc(r.json.mcpUrlWithToken) + '</p>' + 783 // Deliberately NOT the server's full upgradeHint here. That 784 // sentence ends "buying one at postcopilot.ai/threads-mcp-connector" 785 // â which is this page, with the buttons a section below, so quoting 786 // it reads like being sent somewhere you already are. The plan NAMES 787 // are safe to author client-side; the LIMITS are not, and none are 788 // quoted below. 789 (r.json.entitlement && !r.json.entitlement.webPro 790 ? '<p class="plans-fine">Exports and video downloads are on the free allowance ' + 791 'for this account. The $2 day pass or Queue Pro buttons below lift them, on this same ' + 792 'connector, with nothing to reconnect.</p>' 793 : '<p class="plans-fine">Your plan applies to it already: exports and video ' + 794 'downloads are unmetered.</p>'); 795 }).catch(function () { 796 create.disabled = false; 797 create.textContent = regenerate ? 'Regenerate my connector' : 'Create my connector'; 798 document.getElementById('cpOut').innerHTML = 799 '<p class="plans-fine">Network error. Nothing was changed — try again.</p>'; 800 }); 801 }); 802 } 803 804 var linkOpen = document.getElementById('cpLinkOpen'); 805 if (linkOpen) { 806 linkOpen.addEventListener('click', function () { 807 document.getElementById('cpOut').innerHTML = 808 '<p class="plans-fine" style="margin-top:18px;"><strong>Paste a connector token you already ' + 809 'hold.</strong> It starts with <code>pcb_</code> — either the token on its own ' + 810 'or the whole URL, we will take the token out of it. The token itself does not change: whatever ' + 811 'is already in Claude keeps working.</p>' + 812 '<p><input id="cpToken" type="text" inputmode="latin" autocomplete="off" spellcheck="false" ' + 813 'placeholder="pcb_â¦" aria-label="Connector token" ' + 814 'style="width:100%;box-sizing:border-box;padding:12px 14px;border-radius:10px;' + 815 'border:1px solid var(--border);background:var(--surface-2);color:var(--text);' + 816 'font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:14px;"></p>' + 817 '<div class="hero-ctas"><button class="cta" type="button" id="cpLinkGo">Link it</button></div>' + 818 '<p class="plans-fine" id="cpLinkMsg"></p>'; 819 820 document.getElementById('cpLinkGo').addEventListener('click', function () { 821 var msg = document.getElementById('cpLinkMsg'); 822 var raw = (document.getElementById('cpToken').value || '').trim(); 823 // Accept the whole URL as well as the bare token: what people have to 824 // hand is usually a URL, so demanding the token alone would fail for 825 // the most likely paste. 826 var m = /pcb_[A-Za-z0-9_-]{20,}/.exec(raw); 827 if (!m) { msg.textContent = 'That does not contain a connector token. It starts with "pcb_".'; return; } 828 msg.textContent = 'Linkingâ¦'; 829 track('connector_web_link', {}); 830 api('POST', '/api/connector/web/link', { token: m[0] }).then(function (r) { 831 if (r.status !== 200) { msg.textContent = r.json.error || 'Could not link that connector.'; return; } 832 var e = r.json.entitlement || {}; 833 msg.innerHTML = r.json.alreadyLinked 834 ? 'That connector was already linked to this account.' 835 : '<strong>Linked.</strong>
835 Nothing to reconnect — the URL in Claude is unchanged.' + 836 (e.webPro 837 ? ' Your plan now applies: exports and video downloads are unmetered.' 838 : ' ' + esc(e.upgradeHint || '')); 839 }).catch(function () { msg.textContent = 'Network error. Nothing was changed â try again.'; }); 840 }); 841 }); 842 } 843 } 844 845 // Signed in: the hero and closing buttons stop pointing at Google and point 846 // at the Create button instead, with the matching gtag event name. 847 function markSignedIn() { 848 var ctas = document.querySelectorAll('.js-connector-cta'); 849 for (var i = 0; i < ctas.length; i++) { 850 ctas[i].setAttribute('href', '#connect-plan'); 851 ctas[i].setAttribute('data-event', 'click_connector_create'); 852 ctas[i].textContent = 'Create my connector'; 853 } 854 } 855 856 // Back from Google sign-in. The OAuth callback appends "?auth=ok" to the 857 // return path, so it cannot carry a #fragment â land the user on the 858 // Create button here instead, then drop the flag so a reload doesn't jump. 859 function landAfterSignIn() { 860 if (!/[?&]auth=ok(&|$)/.test(location.search)) return; 861 var target = document.getElementById('connect-plan'); 862 if (!target) return; 863 var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 864 target.scrollIntoView({ behavior: reduce ? 'auto' : 'smooth', block: 'start' }); 865 var btn = document.getElementById('cpCreate'); 866 if (btn) { try { btn.focus({ preventScroll: true }); } catch (_) {} }
867 try { 868 var q = location.search.replace(/([?&])auth=ok(&|$)/, function (_, a, b) { return b ? a : ''; }).replace(/[?&]$/, ''); 869 history.replaceState(null, '', location.pathname + q + location.hash); 870 } catch (_) {} 871 } 872 873 api('GET', '/api/connector/web/status').then(function (r) { 874 // 401 is the ordinary signed-out case, not an error: leave the authored 875 // sign-in markup exactly as it is. 876 if (r.status === 401) return; 877 if (r.status !== 200) return; 878 render(r.json); 879 markSignedIn(); 880 }).catch(function () { /* keep the signed-out markup */ }) 881 .then(landAfterSignIn); 882 })(); 883 </script>
883 884
884<script> 885 // "Or try it without signing in" points at a closed <details>; open it. 886 (function () { 887 function openTarget() { 888 var id = location.hash && location.hash.slice(1); 889 var el = id && document.getElementById(id); 890 if (el && el.tagName === 'DETAILS') el.open = true; 891 } 892 window.addEventListener('hashchange', openTarget); 893 document.addEventListener('click', function (e) { 894 var a = e.target.closest && e.target.closest('a[href^="#faq-"]'); 895 if (!a) return; 896 var el = document.getElementById(a.getAttribute('href').slice(1)); 897 if (el && el.tagName === 'DETAILS') el.open = true; 898 }); 899 openTarget(); 900 })(); 901 </script>
901 902</body> 903</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.