Telegram Profile Scraper: Channel, Group, Bot & User Info avatar

Telegram Profile Scraper: Channel, Group, Bot & User Info

Pricing

from $1.50 / 1,000 profiles

Go to Apify Store
Telegram Profile Scraper: Channel, Group, Bot & User Info

Telegram Profile Scraper: Channel, Group, Bot & User Info

Telegram scraper for profiles in bulk: from usernames or t.me links, each telegram channel, group, bot or user with the exact subscriber or member count, title, bio, photo, verified, numeric id, newest post. Optional channel posts with views, reactions, comments and keyword search. No login.

Pricing

from $1.50 / 1,000 profiles

Rating

0.0

(0)

Developer

Hyperbach

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

4

Monthly active users

3 days ago

Last modified

Share

Telegram channel, group, bot and user profiles from a list of usernames or t.me links: the exact subscriber or member count as Telegram writes it, the type, title, description, photo, verified mark, numeric id and newest post — one row per entity, and a free row that says why for a name that does not exist. Add the newest posts on request, newest first, with views as shown, reactions (paid Stars included), media, link previews, polls, buttons and comments; the creation date and the linked discussion group; date windows and in-channel search; and on a schedule, only new posts and the change of the count since the last run. No login, no Telegram account, no API key, proxies handled for you.

Why this Telegram profile scraper

  • Exact counts, labelled. The profile page writes the exact count ("10 493 438 subscribers"); the channel preview rounds it ("10.5M"). Every row carries the exact count with count_type and the line as written, next to the rounded subscribers_shown. Groups get members and members online, bots their monthly users.
  • The right type, and honest misses. Every row says channel, group, bot or user. Telegram answers a missing username with a normal-looking page — and answers a rate-limited reader with the same page. Each "not found" here was read on two different exits before it was written, and costs nothing. On our 100-name test list: 60 channels, 10 groups, 8 users and 22 missing names, the same split as a separate read of the source.
  • Newest posts first. Telegram's web preview lists posts oldest first; in our test of the lane, 9 rival runs returned the oldest posts of the page as "the latest". Here posts come newest first and walk back as far as you ask, with views exactly as shown and flagged when rounded (no "2" for 2.09M), reactions with paid Stars, media links, link previews, polls, buttons, forwards and replies. Ready-made: Telegram channel photos and videos: links from the newest posts.
  • Facts other public-page tools do not give. The numeric id of every public channel (and of public groups), in Telegram's and in the Bot API's form; the creation date from the channel's first post ("Channel created"); the linked discussion group; comments of each post. Ready-made: Vet Telegram channels: creation date, id, views per post.
  • Built for lists and schedules. Usernames, @handles, profile, preview, post and invite links in one list; the same entity given three ways is one row. onlyNewPosts delivers only posts published since the last run; onlyChanged delivers a profile only when it changed; a named memory adds the count's change per day and its history.
  • Light and fast. No browser and no Telegram account: one small page per profile. 100 names in about a minute; misses and rows for values that are not usernames are free.

Who it's for

  • Marketers and growth teams — vet channels and groups before a placement: exact subscribers or members, posting rate, views and reactions of the newest posts, verified mark.
  • Researchers and analysts — a list of channels with their newest posts, dates, views as shown and reactions, or a date window of a channel's history, in one row shape.
  • Monitoring and trust teams — a scheduled list that reports what changed: new posts only, count changes per day, titles and descriptions that moved, names that disappeared.
  • Developers and agents — typed fields, one row per input in input order, a free labelled row for every miss, and a run summary to check a pipeline against.

Quick start

Profiles of a channel, a bot and a group

{
"usernames": [
"durov",
"BotFather",
"https://t.me/tginfochat"
]
}

The 20 newest posts of each channel

{
"usernames": [
"durov",
"telegram"
],
"maxPostsPerChannel": 20
}

Posts of a date window, with comments

{
"usernames": [
"tginfo"
],
"postsNewerThan": "2026-09-01",
"postsOlderThan": "2026-10-01",
"maxCommentsPerPost": 10
}

Deep profile: creation date, ids, linked discussion group

{
"usernames": [
"durov",
"tginfo",
"tginfochat"
],
"deepProfile": true
}

A daily monitor: new posts and changed profiles only

{
"usernames": [
"durov",
"tginfo"
],
"maxPostsPerChannel": 50,
"onlyNewPosts": true,
"onlyChanged": true
}

Output

One profile row per entity you named (or a free row saying why there is none) and, when you ask for posts, one post row per post (row_type says which):

fieldmeaning
row_typeprofile = one per unique input (the entity's record, or a free row saying why there is none); post = one per post of a channel.
inputThe value as you gave it (the first form, when the same entity was given several ways). On post rows: the channel's input.
input_indexThe input's 1-based position in your list.
inputs_mergedLater values of your list that named the same entity (@durov and its link after durov); read once, one row.
profile_statusok = a public channel, group, bot or user (charged). Free rows: not_found (no public entity has the name — read on two exits, because Telegram serves a missing name and a rate-limited reader the same page), invalid (not a Telegram username or link), failed (Telegram answered something else; read again later).
status_detailWhy a row has no record, in words (null on ok rows).
scraped_atWhen the row was read (UTC).
usernameThe public username, as Telegram writes it (null for an invite link).
entity_typechannel, group, bot or user, read from the page: the count line (subscribers, members, monthly users), then the title and the button.
titleThe channel's, group's or bot's title, or the user's name.
descriptionThe description or bio, line breaks and emoji kept.
profile_urlThe profile's public page (t.me/<username>).
avatar_urlThe profile photo on Telegram's CDN (a signed link that changes on each read; null when there is no photo).
verifiedTelegram's verified mark.
warning_labelTelegram's own warning label on the profile, as its page shows it next to the title (FAKE, SCAM); null when there is none. It is never part of title.
invite_linkThe invite link you gave, for a group or channel read through one.
countThe entity's headline count, exact as Telegram writes it on the profile page: subscribers of a channel, members of a group, monthly users of a bot (null for a user).
count_typeWhat count counts: subscribers, members or monthly_users.
count_textThe count line exactly as the page shows it ("10 493 438 subscribers", "5 365 members, 1 163 online").
counts_precisionexact when count is the page's exact figure.
subscribersA channel's subscribers, exact.
subscribers_shownThe subscriber count as the channel's preview rounds it ("10.5M").
membersA group's members, exact.
members_onlineA group's members online at the moment of the read.
monthly_usersA bot's monthly users, exact.
chat_idThe numeric id of a channel (from its public posts) or of a public group (deepProfile, from its first message), in Telegram's own form (1006503122). Null for bots and users: no logged-out page shows theirs.
bot_api_idThe same id in the Bot API's form (-100 followed by chat_id).
has_previewThe channel shows its posts on the web (its /s/ preview); only such channels have post rows.
preview_urlThe channel's web preview.
photos_countPhotos the channel posted, from its preview (rounded above 999, as counters_shown says).
videos_countVideos the channel posted (rounded above 999).
files_countFiles the channel posted (rounded above 999; 0 when the preview shows no files counter).
links_countLinks the channel posted (rounded above 999).
counters_shownThe preview's counters exactly as written (subscribers "10.5M", photos "1.38K", …).
counters_precisionexact when every counter is written in full, rounded when one is written rounded ("1.38K" above 999).
latest_post_idThe channel's newest post (the last one on its preview: the preview lists posts oldest first).
latest_post_atWhen the newest post was published (UTC).
latest_post_urlThe newest post's link.
created_atdeepProfile: when the channel or group was created, or the earliest date the page shows (see created_at_source).
created_at_sourcechannel_created = post 1, Telegram's "Channel created" message (exact); first_post = post 1 is an ordinary post; oldest_post = post 1 is gone, the oldest post left (the channel existed by then); first_message = a group's first message (the group existed by then); post_1_embed = a channel without a public preview: the date of its post 1 in Telegram's embed widget, which does not show whether post 1 is the "Channel created" message (the channel existed by then).
linked_chat_idThe id of a channel's linked discussion group (deepProfile or comments), from the comments widget; on post rows, the group the comments came from.
engagement_postsHow many of the newest posts (the preview's first page, service messages left out) the engagement fields are computed over.
avg_viewsAverage views of those posts, as the page shows them (rounded above 999).
median_viewsMedian views of those posts.
avg_reactionsAverage reactions per post (all emoji and paid Stars together).
view_rateMedian views ÷ subscribers. On post rows: the post's views ÷ the channel's subscribers.
engagement_rateAverage reactions ÷ average views.
posts_per_weekPosting rate over the span of those posts.
dominant_scriptThe writing system most letters of the description and the newest posts are in (Latin, Cyrillic, Arabic, Han, …); links and handles left out.
posts_requestedPosts asked for this channel (maxPostsPerChannel, or 100 when a post filter set it).
posts_deliveredPost rows this run delivered for the channel.
posts_noteWhy a channel delivered fewer posts than asked (no older post, no public preview, Telegram's search ended, the newest an earlier run delivered, maxItems or your charge limit reached), and how comments were read.
deep_notedeepProfile: what could not be read and why — a bot's or a user's id and creation date (Telegram's web pages do not show them; they need a Telegram login, which this Actor does not use), a group whose first message is gone, a channel whose post 1 is gone (created_at is then a bound), a channel without a public preview (its id and date come from its post 1's embed; no linked group), an invite link.
change_typeWith the memory on: new, changed or unchanged against the last time this profile was delivered.
changed_fieldsWhich watched fields changed (count, title, description, latest_post_id, …).
previous_read_atWhen the profile was last delivered.
previous_countcount at that time.
count_changecount minus previous_count.
count_change_per_daycount_change per day since the previous read (null under an hour).
first_read_atWhen the memory first read this profile.
times_readHow many runs read it, this one included.
count_historyThe memory's last 30 reads: time, count, count type, online.
markdownincludeMarkdown: the profile and its delivered posts as Markdown.
run_tagYour runTag, on every row.
channel_titleOn post rows: the channel's title.
channel_subscribersOn post rows: the channel's exact subscriber count at the time of the run.
post_idThe post's number in its channel. Deduplicate on username + post_id.
post_urlThe post's public link.
published_atWhen the post was published (UTC).
is_editedThe post carries Telegram's "edited" mark.
author_signatureThe author's signature, when the channel signs its posts.
textThe post's text, line breaks and emoji kept.
text_lengthCharacters in text.
hashtagsHashtags of the post.
mentions@usernames the post mentions.
linksLinks in the post's text.
viewsViews as the page shows them, as a number (2.09M → 2090000); views_precision says when it is rounded. Telegram shows exact views only to its apps.
views_shownViews exactly as written ("2.09M").
views_precisionexact (under 1,000) or rounded.
reactionsEach reaction: emoji (or the custom emoji's id), count, paid for Telegram Stars, the count as written and its precision.
reactions_totalAll reactions of the post together.
reactions_precisionrounded when a reaction count is written rounded on the page ("21.4K"), so reactions_total and paid_stars are sums of rounded values; exact otherwise.
paid_starsThe paid Star reactions of the post.
forwarded_fromThe name of the chat a forwarded post came from.
forwarded_from_urlThe original post's link, when public.
reply_to_post_idThe post this one replies to.
mediaPhotos (every photo of an album), videos (with duration), GIFs (gif: a looping clip, no duration), round videos, voice notes, music files (title, performer), documents (name, size) and stickers, with their CDN links (signed, valid for a while). A video too big for Telegram's web page has its thumbnail and duration, too_big: true and no file link (open the post in the app).
media_typesThe kinds of media in the post.
media_not_supportedTrue when Telegram's web page does not show the post's media ("Please open Telegram to view this post"): open the post in the app.
link_previewThe link preview: URL, site, title, description, image.
pollA poll: question, type, voters (and as written, with its precision: "71.7K" is rounded), options with their share in percent.
buttonsInline buttons under the post: row, text, URL.
matched_searchYour postsSearch, on the posts it found.
comments_countHow many comments the post has (the widget's own count).
comments_statusok, not_available (Telegram's "Discussion is not available": no public comments for the post), or not_asked (the channel's newest 5 posts had no discussion, so older posts were not asked; see posts_note).
commentsmaxCommentsPerPost: the comments: author name, handle (when public), text or media (a sticker, photo or video), date, the comment it replies to and reactions.

Example record:

{
"row_type": "profile",
"input": "durov",
"input_index": 1,
"inputs_merged": [
"@durov",
"https://t.me/durov"
],
"profile_status": "ok",
"status_detail": null,
"scraped_at": "2026-10-06T20:16:43Z",
"username": "durov",
"entity_type": "channel",
"title": "Pavel Durov",
"description": "Founder of Telegram.",
"profile_url": "https://t.me/durov",
"avatar_url": "https://cdn4.telesco.pe/file/M-TyKlOPLmDf65MjCoCy6WQAAGHv6kEmgSsdHU-98ome4oWbTEAAdsuraeQEFiRHGYWIUdPJKRaT73TGs6QuHxgyF6ELLDS6PE4se9WXx_WYQhf5X4F2XD6TY6CxLUtmn8OWc58w_oT25iNx30RAk6tVioIfIwAsc8m0htRA1pHh3jA6Y6t0Xtjrh6tLu-vBy7F_RmNql9LDoerXArtXkH_UK-BJY7fkel3g8TshvwhElfyOxkVO74VaxMA_HHFf1IBfvLD9wsrsmwjQ8RPbf3jLfw5p-1CaCIuZRyyPAicwDZS4Qqxz3kCPCbCo5V-kNvxg8VU8FH-KnyymhAoVqQ.jpg",
"verified": true,
"warning_label": null,
"invite_link": null,
"count": 10491495,
"count_type": "subscribers",
"count_text": "10 491 495 subscribers",
"counts_precision": "exact",
"subscribers": 10491495,
"subscribers_shown": "10.5M",
"members": null,
"members_online": null,
"monthly_users": null,
"chat_id": 1006503122,
"bot_api_id": -1001006503122,
"has_preview": true,
"preview_url": "https://t.me/s/durov",
"photos_count": 102,
"videos_count": 46,
"files_count": 0,
"links_count": 200,
"counters_shown": {
"subscribers": "10.5M",
"photos": "102",
"videos": "46",
"links": "200"
},
"counters_precision": "exact",
"latest_post_id": 548,
"latest_post_at": "2026-09-11T16:04:02Z",
"latest_post_url": "https://t.me/durov/548",
"created_at": "2015-10-28T18:20:58Z",
"created_at_source": "channel_created",
"linked_chat_id": null,
"engagement_posts": 20,
"avg_views": 5529500.0,
"median_views": 4390000.0,
"avg_reactions": 132263.4,
"view_rate": 0.4184,
"engagement_rate": 0.02392,
"posts_per_week": 1.51,
"dominant_script": "Latin",
"posts_requested": 2,
"posts_delivered": 2,
"posts_note": null,
"deep_note": null,
"change_type": null,
"changed_fields": null,
"previous_read_at": null,
"previous_count": null,
"count_change": null,
"count_change_per_day": null,
"first_read_at": null,
"times_read": null,
"count_history": null,
"markdown": "# Pavel Durov (@durov)\n\nchannel · 10,491,495 subscribers · verified\n\nFounder of Telegram.\n\nid 1006503122 · created 2015-10-28 · latest post 2026-09-11\n\n## Posts\n\n- [2026-09-11](https://t.me/durov/548) · 2.1M views: 🤝 Telegram has become the sponsor of Codeforces — the largest competitive programming platform in the world. ⚡CodeForces organizes over 100 coding contests every year and has 4 million contestants signed up. 🌱 Since 2010, I've supported Codeforces through the companies I sta…\n- [2026-09-06](https://t.me/durov/547) · 2.99M views: 💸 In just one month, Telegram has awarded over $2,222,000 to some of the brightest minds on our planet. 🎨 This week alone we distributed $222,000 among the winners of our two latest competitions — the Design Contest and the Digital Freedom Contest. On top of that, over the p…\n",
"run_tag": null,
"channel_title": null,
"channel_subscribers": null,
"post_id": null,
"post_url": null,
"published_at": null,
"is_edited": null,
"author_signature": null,
"text": null,
"text_length": null,
"hashtags": null,
"mentions": null,
"links": null,
"views": null,
"views_shown": null,
"views_precision": null,
"reactions": null,
"reactions_total": null,
"reactions_precision": null,
"paid_stars": null,
"forwarded_from": null,
"forwarded_from_url": null,
"reply_to_post_id": null,
"media": null,
"media_types": null,
"media_not_supported": null,
"link_preview": null,
"poll": null,
"buttons": null,
"matched_search": null,
"comments_count": null,
"comments_status": null,
"comments": null
}

Pricing

Pay only for the rows a run delivers, with no start fee and no platform usage billed to you. Prices fall with your Apify plan.

per 1,000FreeStarterScaleBusiness
Profile (profile)$3.00$2.55$2.10$1.50
Post (post)$1.50$1.275$1.05$0.75
Comment on a post row (comment)+$0.50+$0.425+$0.35+$0.25

A profile is $3.00 per 1,000 entities found on the Free plan and $1.50 on Business; a post $1.50 per 1,000 on Free. The deep profile (creation date, group id, linked discussion group) is part of the profile price. + comments are charged per comment delivered on a post row with maxCommentsPerPost. Free: the row for a name that does not exist (read on two exits), a value that is not a Telegram username or link, a page Telegram did not serve, and a run that failed before its first row. With onlyChanged, a profile that did not change is not delivered and not charged. With onlyNewPosts, each channel's profile row is still delivered and charged on every run; only the post rows are limited to new posts. maxItems is exact; before the first request the log says the most the run can cost at your plan's prices. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.

Usage patterns

  • A list check — Paste hundreds of usernames or links: each comes back as one row in your order (input_index), with its type and exact count, or as a free not_found / invalid row. Duplicates in any form are read once (inputs_merged). Ready-made: Telegram subscriber and member counts for a list of usernames.
  • A channel's posts — maxPostsPerChannel with postsNewerThan / postsOlderThan reads a channel's posts newest first; an old window is reached by a jump on post ids, not by reading every newer page. postsSearch uses Telegram's own channel search; maxCommentsPerPost adds comments. Ready-made: Scrape a Telegram channel: its profile and 20 newest posts, Telegram channel posts from the last 7 days, with comments, Search Telegram channel posts for a keyword.
  • A schedule — Save a task with your list and onlyNewPosts and run it daily: each run delivers only the posts published since the last one, and each channel's profile row with today's count (a profile row is charged on every run). Add onlyChanged to skip, free, the profiles that did not change since they were last delivered (a new post is a change); stateStoreName keeps the memory under a name you choose and adds count_change, count_change_per_day and count_history. Ready-made: Monitor Telegram channels daily: new posts and count changes.
  • For a language model — includeMarkdown adds the profile and its posts as one Markdown text per profile row, ready for a prompt or a note.

Input configuration

fieldtypedefaultwhat it does
usernamesarray[]Telegram channels, groups, bots and users, one per line, in any form: durov, @durov, https://t.me/durov, t.me/s/durov, telegram.me/durov, a post link (t.me/durov/548 reads the channel) or an invite link (t.me/+AbC…, t.me/joinchat/…). One row per entity: the same entity given twice is read once. A value that is not a Telegram username or link comes back as a free row that says why.
maxPostsPerChannelinteger0How many of each channel's posts to deliver as post rows, newest first; 0 = the profile row only (it still carries the newest post's id and date). Only channels with a public preview have posts on the web; groups, bots and users have none. With a post filter (dates, search, comments or only new posts) and 0 here, up to 100 posts per channel are read.
postsNewerThanstring""Only posts published on or after this date: 2026-09-01, or a span back from today such as 30 days, 2 weeks, 6 months (UTC). With Posts per channel at 0, up to 100 posts per channel are read.
postsOlderThanstring""Only posts published before this date (same forms as Posts from). The Actor jumps to that point of the channel by post id instead of reading every newer post.
postsSearchstring""Only posts that Telegram's own channel search finds for this text (a word, a phrase or a #hashtag), newest first. Telegram's search is shallow on large channels: the row says how many posts it returned.
maxCommentsPerPostinteger0Comments to add to each post row (comments: author, handle, text, date, reactions), from the channel's linked discussion group; 0 = none. A channel without public comments says so on each post (comments_status). Charged per comment delivered.
deepProfilebooleanfalseOne or two more requests per channel or group: the creation date (a channel's first post, Telegram's "Channel created" message; a group's first message), the numeric id of a public group, and a channel's linked discussion group (its id). Each fact says where it came from (created_at_source).
includeMarkdownbooleanfalseAdd a markdown text to each profile row: the profile and its delivered posts as Markdown, for a language model's context or a note.
onlyNewPostsbooleanfalseDeliver only the posts published after the newest post an earlier run of the same task delivered: run a channel list daily and get only its new posts. Each channel's profile row (today's count) is still delivered and charged on every run; add Only changed profiles to skip unchanged ones. Turns the memory on.
onlyChangedbooleanfalseDeliver (and charge) a profile only when its title, description, type, verified mark, warning label, exact count, newest post or username changed since the last time it was delivered. Every delivered profile carries change_type, the previous count and the change. Turns the memory on.
stateStoreNamestring""Name of the memory between runs. Given, it turns the memory on: every profile row gets the change of its count since the last delivered read, per day, and a history of counts. Empty = derived from your usernames when Only new posts or Only changed profiles is on.
maxItemsinteger0The most profile and post rows this run delivers (and charges), together. 0 = no limit. Free rows (not found, not a username) do not count.
runTagstring""A label copied onto every row (run_tag), to tell runs apart in a shared dataset.

Errors

A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:

  • the status message starts with INPUT REJECTED;
  • the dataset holds one row, {"error": true, "code": "…", "message": "…"}, and no results;
  • the key-value store record ERROR holds the same object.

From code, check error on the first row before reading results.

A search that matches nothing is not an error: the dataset is empty and nothing is charged. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.

FAQ

Why is a name "not found" here when I can open it in the app?

The row says what the public web page shows. A user who hides their username from the web, a private group or channel, or a name used only inside the app has no public page. Every miss was read on two exits, so it is not a rate limit.

Are the views exact?

Telegram shows exact views only inside its apps; the public pages round them above 999 ("2.09M"). views is that value as a number and views_precision says rounded; views_shown keeps the text. The subscriber and member counts on the profile row are exact.

Can I get bot commands, a user's id, last seen or premium status?

No. Telegram serves those only to a logged-in account, and this Actor does not log in. The numeric id is given for public channels and groups, where the public pages carry it.

What is charged?

A profile row of an entity that was found, a post row, and each comment on a post row. Rows for names that do not exist, values that are not usernames, pages Telegram did not serve, and a run that failed before its first row are free; a run that stops early (a timeout, an abort) is charged for the rows it delivered. With onlyNewPosts, each channel's profile row is still charged on every run; with onlyChanged, an unchanged profile is not delivered and not charged. maxItems caps profile and post rows together. The prices are in the Pricing section above.

Does it read private channels or join groups?

No. It reads what Telegram shows to anyone on the web: profile pages, the public preview of channels, the public comments widget. An invite link gives the title and member count its page shows.

Can an AI agent use it (MCP)?

Yes. Apify's MCP server (https://mcp.apify.com) offers Store Actors as tools to Claude, Cursor and other MCP clients: add this Actor and the agent sends usernames and gets the rows back. The synchronous API (run-sync-get-dataset-items) does the same in one HTTP call.

Integration

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/telegram-profile-scraper').call({"usernames": ["durov", "BotFather", "https://t.me/tginfochat"]});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/telegram-profile-scraper').call(run_input={'usernames': ['durov', 'BotFather', 'https://t.me/tginfochat']})
items = client.dataset(run['defaultDatasetId']).list_items().items

CLI

$apify call hyperbach/telegram-profile-scraper --input '{"usernames": ["durov", "BotFather", "https://t.me/tginfochat"]}'

REST

curl -X POST "https://api.apify.com/v2/acts/hyperbach~telegram-profile-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' -d '{"usernames": ["durov", "BotFather", "https://t.me/tginfochat"]}'

Support

apify@hyperbach.com

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.