@unavatar/core 3.13.0 → 3.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -68
- package/package.json +1 -1
- package/src/providers/behance.js +12 -0
- package/src/providers/index.js +2 -0
package/README.md
CHANGED
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
- [Table of Contents](#table-of-contents)
|
|
4
4
|
- [Introduction](#introduction)
|
|
5
5
|
- [Quick start](#quick-start)
|
|
6
|
+
- [Authentication](#authentication)
|
|
7
|
+
- [Pricing](#pricing)
|
|
8
|
+
- [Cache](#cache)
|
|
6
9
|
- [Query parameters](#query-parameters)
|
|
7
10
|
- [TTL](#ttl)
|
|
8
11
|
- [Fallback](#fallback)
|
|
9
12
|
- [JSON](#json)
|
|
10
|
-
- [Pricing](#pricing)
|
|
11
13
|
- [Providers](#providers)
|
|
12
14
|
- [Apple Music](#apple-music)
|
|
13
15
|
- [Bluesky](#bluesky)
|
|
14
16
|
- [DeviantArt](#deviantart)
|
|
15
|
-
- [Discord](#discord)
|
|
16
17
|
- [Dribbble](#dribbble)
|
|
17
18
|
- [DuckDuckGo](#duckduckgo)
|
|
18
19
|
- [GitHub](#github)
|
|
@@ -29,12 +30,10 @@
|
|
|
29
30
|
- [Patreon](#patreon)
|
|
30
31
|
- [Printables](#printables)
|
|
31
32
|
- [Reddit](#reddit)
|
|
32
|
-
- [Snapchat](#snapchat)
|
|
33
33
|
- [SoundCloud](#soundcloud)
|
|
34
34
|
- [Spotify](#spotify)
|
|
35
35
|
- [Substack](#substack)
|
|
36
36
|
- [Telegram](#telegram)
|
|
37
|
-
- [Threads](#threads)
|
|
38
37
|
- [TikTok](#tiktok)
|
|
39
38
|
- [Twitch](#twitch)
|
|
40
39
|
- [Vimeo](#vimeo)
|
|
@@ -49,16 +48,17 @@
|
|
|
49
48
|
|
|
50
49
|
- [Introduction](#introduction)
|
|
51
50
|
- [Quick start](#quick-start)
|
|
51
|
+
- [Authentication](#authentication)
|
|
52
|
+
- [Pricing](#pricing)
|
|
53
|
+
- [Cache](#cache)
|
|
52
54
|
- [Query parameters](#query-parameters)
|
|
53
55
|
- [TTL](#ttl)
|
|
54
56
|
- [Fallback](#fallback)
|
|
55
57
|
- [JSON](#json)
|
|
56
|
-
- [Pricing](#pricing)
|
|
57
58
|
- [Providers](#providers)
|
|
58
59
|
- [Apple Music](#apple-music)
|
|
59
60
|
- [Bluesky](#bluesky)
|
|
60
61
|
- [DeviantArt](#deviantart)
|
|
61
|
-
- [Discord](#discord)
|
|
62
62
|
- [Dribbble](#dribbble)
|
|
63
63
|
- [DuckDuckGo](#duckduckgo)
|
|
64
64
|
- [GitHub](#github)
|
|
@@ -75,12 +75,10 @@
|
|
|
75
75
|
- [Patreon](#patreon)
|
|
76
76
|
- [Printables](#printables)
|
|
77
77
|
- [Reddit](#reddit)
|
|
78
|
-
- [Snapchat](#snapchat)
|
|
79
78
|
- [SoundCloud](#soundcloud)
|
|
80
79
|
- [Spotify](#spotify)
|
|
81
80
|
- [Substack](#substack)
|
|
82
81
|
- [Telegram](#telegram)
|
|
83
|
-
- [Threads](#threads)
|
|
84
82
|
- [TikTok](#tiktok)
|
|
85
83
|
- [Twitch](#twitch)
|
|
86
84
|
- [Vimeo](#vimeo)
|
|
@@ -115,6 +113,161 @@ The service is exposed in **unavatar.io** via provider endpoints:
|
|
|
115
113
|
|
|
116
114
|
Use the `/:provider/:key` format for all lookups. You can read more about available providers in [providers](https://unavatar.io/docs#providers).
|
|
117
115
|
|
|
116
|
+
## Authentication
|
|
117
|
+
|
|
118
|
+
The anonymous requests works without authentication. They are limited to 25 requests/day per IP address.
|
|
119
|
+
|
|
120
|
+
For [PRO](https://unavatar.io/checkout) users, the requests must include the API key as the `x-api-key` request header:
|
|
121
|
+
|
|
122
|
+
``` bash
|
|
123
|
+
curl -H "x-api-key: YOUR_API_KEY" "https://[unavatar.io/github/kikobeats"](https://unavatar.io/github/kikobeats")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
``` javascript
|
|
127
|
+
await fetch('https://[unavatar.io/github/kikobeats',](https://unavatar.io/github/kikobeats',) {
|
|
128
|
+
headers: {
|
|
129
|
+
'x-api-key': process.env.UNAVATAR_API_KEY
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
``` python
|
|
135
|
+
import os
|
|
136
|
+
import requests
|
|
137
|
+
|
|
138
|
+
response = requests.get(
|
|
139
|
+
'https://[unavatar.io/github/kikobeats',](https://unavatar.io/github/kikobeats',)
|
|
140
|
+
headers={'x-api-key': os.environ['UNAVATAR_API_KEY']}
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
``` golang
|
|
145
|
+
package main
|
|
146
|
+
|
|
147
|
+
import (
|
|
148
|
+
"net/http"
|
|
149
|
+
"os"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
func main() {
|
|
153
|
+
req, _ := http.NewRequest("GET", "https://[unavatar.io/github/kikobeats",](https://unavatar.io/github/kikobeats",) nil)
|
|
154
|
+
req.Header.Set("x-api-key", os.Getenv("UNAVATAR_API_KEY"))
|
|
155
|
+
|
|
156
|
+
resp, _ := http.DefaultClient.Do(req)
|
|
157
|
+
defer resp.Body.Close()
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
``` ruby
|
|
162
|
+
require 'net/http'
|
|
163
|
+
require 'uri'
|
|
164
|
+
|
|
165
|
+
uri = URI('https://[unavatar.io/github/kikobeats')](https://unavatar.io/github/kikobeats'))
|
|
166
|
+
request = Net::HTTP::Get.new(uri)
|
|
167
|
+
request['x-api-key'] = ENV['UNAVATAR_API_KEY']
|
|
168
|
+
|
|
169
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
|
170
|
+
http.request(request)
|
|
171
|
+
end
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
``` php
|
|
175
|
+
$ch = curl_init('https://[unavatar.io/github/kikobeats');](https://unavatar.io/github/kikobeats');)
|
|
176
|
+
|
|
177
|
+
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
178
|
+
'x-api-key: ' . getenv('UNAVATAR_API_KEY'),
|
|
179
|
+
]);
|
|
180
|
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
181
|
+
|
|
182
|
+
$response = curl_exec($ch);
|
|
183
|
+
curl_close($ch);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
If the API key is invalid, the service returns `401` with code `EAPIKEY`.
|
|
187
|
+
|
|
188
|
+
Rate limit status can be verified using these response headers:
|
|
189
|
+
|
|
190
|
+
| Header | Description |
|
|
191
|
+
| ------------------------ | -------------------------------------------------------------- |
|
|
192
|
+
| `x-rate-limit-limit` | Maximum anonymous requests allowed in the current daily window |
|
|
193
|
+
| `x-rate-limit-remaining` | Requests remaining in the current window |
|
|
194
|
+
| `x-rate-limit-reset` | UTC epoch seconds when the current window resets |
|
|
195
|
+
|
|
196
|
+
``` bash
|
|
197
|
+
$ curl -I https://[unavatar.io/github/kikobeats](https://unavatar.io/github/kikobeats)
|
|
198
|
+
|
|
199
|
+
x-rate-limit-limit: 25
|
|
200
|
+
x-rate-limit-remaining: 24
|
|
201
|
+
x-rate-limit-reset: 1744243200
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Pricing
|
|
205
|
+
|
|
206
|
+
Unavatar pricing is simple: you can start on the anonymous free tier, then authenticate with `x-api-key` to get additional included usage and metered billing for higher volume.
|
|
207
|
+
|
|
208
|
+
| Scenario | Included free usage | Billing |
|
|
209
|
+
| -------------------------------------------- | ---------------------- | -------------------------------- |
|
|
210
|
+
| Anonymous (no API key) | 25 requests/day per IP | Free |
|
|
211
|
+
| Authenticated origin requests (`x-api-key`) | 50 origin requests/day | Metered monthly after free quota |
|
|
212
|
+
| Proxy requests (`datacenter`, `residential`) | None | Always metered |
|
|
213
|
+
|
|
214
|
+
For higher usage, the **[PRO](https://unavatar.io/checkout)** plan is usage-based billing that includes the 50 free daily origin requests, metered overage, and custom TTL.
|
|
215
|
+
|
|
216
|
+
Every request has a cost in tokens (**\$0.005 per token**) based on the proxy tier needed to resolve the avatar:
|
|
217
|
+
|
|
218
|
+
| Proxy tier | Tokens | Cost |
|
|
219
|
+
| ----------- | :----: | :-----: |
|
|
220
|
+
| Origin | 1 | \$0.005 |
|
|
221
|
+
| Datacenter | +2 | \$0.015 |
|
|
222
|
+
| Residential | +4 | \$0.025 |
|
|
223
|
+
|
|
224
|
+
The proxy tier used is returned in the `x-proxy-tier` response header, and the total cost in the `x-unavatar-cost` header.
|
|
225
|
+
|
|
226
|
+
``` bash
|
|
227
|
+
$ curl -I -H "x-api-key: YOUR_API_KEY" https://[unavatar.io/instagram/kikobeats](https://unavatar.io/instagram/kikobeats)
|
|
228
|
+
|
|
229
|
+
x-pricing-tier: pro
|
|
230
|
+
x-proxy-tier: origin
|
|
231
|
+
x-unavatar-cost: 1
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
To upgrade, visit [unavatar.io/checkout](https://unavatar.io/checkout). After completing the payment, you'll receive an API key.
|
|
235
|
+
|
|
236
|
+
## Cache
|
|
237
|
+
|
|
238
|
+
Unavatar caches avatar lookups to make repeated requests fast and stable:
|
|
239
|
+
|
|
240
|
+
- The first request for a resource fetches the avatar from upstream and stores it in cache
|
|
241
|
+
- Following requests are served from cache until the [TTL](https://unavatar.io/docs#ttl) expires.
|
|
242
|
+
|
|
243
|
+
For example, if you set `ttl=1h`, the cache behavior looks like this:
|
|
244
|
+
|
|
245
|
+
| Time | Request | Cache status | Plan impact |
|
|
246
|
+
| ----- | ----------------------- | ----------------------------------- | -------------------------- |
|
|
247
|
+
| 10:00 | `GET /github/kikobeats` | MISS (fetched from upstream) | Counts as 1 origin request |
|
|
248
|
+
| 10:05 | `GET /github/kikobeats` | HIT (served from cache) | No usage consumed, no cost |
|
|
249
|
+
| 10:40 | `GET /github/kikobeats` | HIT (served from cache) | No usage consumed, no cost |
|
|
250
|
+
| 11:02 | `GET /github/kikobeats` | MISS (TTL expired, cache refreshed) | Counts as 1 origin request |
|
|
251
|
+
| 11:10 | `GET /github/kikobeats` | HIT (served from cache) | No usage consumed, no cost |
|
|
252
|
+
|
|
253
|
+
To check the cache status in real requests, inspect these response headers:
|
|
254
|
+
|
|
255
|
+
| Header | What to look for |
|
|
256
|
+
| ---------------- | --------------------------------------------------------------------------------------- |
|
|
257
|
+
| `x-cache-status` | `HIT` means served from cache. `MISS` means fetched/refreshed from upstream. |
|
|
258
|
+
| `cache-control` | Shows cache policy and effective TTL (for example `public, max-age=3600` for `ttl=1h`). |
|
|
259
|
+
|
|
260
|
+
``` bash
|
|
261
|
+
$ curl -I -H "x-api-key: YOUR_API_KEY" "https://[unavatar.io/github/kikobeats?ttl=1h"](https://unavatar.io/github/kikobeats?ttl=1h")
|
|
262
|
+
|
|
263
|
+
cache-control: public, max-age=3600
|
|
264
|
+
x-cache-status: HIT
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The same rule applies to anonymous requests: cache hits are free and do not consume the `25 requests/day` limit.
|
|
268
|
+
|
|
269
|
+
After TTL expiration, the next request refreshes the cache and is billed/rate-limited according to the request tier (`anonymous`, `origin`, `datacenter`, or `residential`).
|
|
270
|
+
|
|
118
271
|
## Query parameters
|
|
119
272
|
|
|
120
273
|
### TTL
|
|
@@ -165,40 +318,6 @@ In case you want to get a JSON payload as response, just pass `json=true`:
|
|
|
165
318
|
|
|
166
319
|
e.g., [unavatar.io/github/kikobeats?json](https://unavatar.io/github/kikobeats?json)
|
|
167
320
|
|
|
168
|
-
## Pricing
|
|
169
|
-
|
|
170
|
-
The service is **FREE** for everyone, no registration required, with a daily rate limit of **50 requests** per IP address.
|
|
171
|
-
|
|
172
|
-
For preventing abusive usage, the service has associated a daily rate limit based on requests IP address.
|
|
173
|
-
|
|
174
|
-
You can verify for your rate limit state checking the following headers in the response:
|
|
175
|
-
|
|
176
|
-
- `x-rate-limit-limit`: The maximum number of requests that the consumer is permitted to make per minute.
|
|
177
|
-
- `x-rate-limit-remaining`: The number of requests remaining in the current rate limit window.
|
|
178
|
-
- `x-rate-limit-reset`: The time at which the current rate limit window resets in UTC epoch seconds.
|
|
179
|
-
|
|
180
|
-
For higher usage, the **[PRO](https://unavatar.io/checkout)** plan is a usage-based plan billed monthly that removes rate limits and unlocks custom TTL.
|
|
181
|
-
|
|
182
|
-
Every request has a cost in tokens (**\$0.005 per token**) based on the proxy tier needed to resolve the avatar:
|
|
183
|
-
|
|
184
|
-
| Proxy tier | Tokens | Cost |
|
|
185
|
-
| ----------- | :----: | :-----: |
|
|
186
|
-
| Origin | 1 | \$0.005 |
|
|
187
|
-
| Datacenter | +2 | \$0.015 |
|
|
188
|
-
| Residential | +4 | \$0.025 |
|
|
189
|
-
|
|
190
|
-
The proxy tier used is returned in the `x-proxy-tier` response header, and the total cost in the `x-unavatar-cost` header.
|
|
191
|
-
|
|
192
|
-
``` bash
|
|
193
|
-
$ curl -I -H "x-api-key: YOUR_API_KEY" https://[unavatar.io/instagram/kikobeats](https://unavatar.io/instagram/kikobeats)
|
|
194
|
-
|
|
195
|
-
x-pricing-tier: pro
|
|
196
|
-
x-proxy-tier: origin
|
|
197
|
-
x-unavatar-cost: 1
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
To upgrade, visit [unavatar.io/checkout](https://unavatar.io/checkout). After completing the payment, you'll receive an API key.
|
|
201
|
-
|
|
202
321
|
## Providers
|
|
203
322
|
|
|
204
323
|
### Apple Music
|
|
@@ -240,14 +359,6 @@ Available inputs:
|
|
|
240
359
|
|
|
241
360
|
- slug, e.g., [unavatar.io/deviantart/spyed](https://unavatar.io/deviantart/spyed)
|
|
242
361
|
|
|
243
|
-
### Discord
|
|
244
|
-
|
|
245
|
-
Get any Discord server icon by invite code.
|
|
246
|
-
|
|
247
|
-
Available inputs:
|
|
248
|
-
|
|
249
|
-
- Invite code, e.g., [unavatar.io/discord/eret](https://unavatar.io/discord/eret)
|
|
250
|
-
|
|
251
362
|
### Dribbble
|
|
252
363
|
|
|
253
364
|
Get any Dribbble designer's profile picture by their username.
|
|
@@ -392,14 +503,6 @@ Available inputs:
|
|
|
392
503
|
|
|
393
504
|
- slug, e.g., [unavatar.io/reddit/kikobeats](https://unavatar.io/reddit/kikobeats)
|
|
394
505
|
|
|
395
|
-
### Snapchat
|
|
396
|
-
|
|
397
|
-
Get any Snapchat user's profile picture by their username.
|
|
398
|
-
|
|
399
|
-
Available inputs:
|
|
400
|
-
|
|
401
|
-
- slug, e.g., [unavatar.io/snapchat/teddysdaytoday](https://unavatar.io/snapchat/teddysdaytoday) or [unavatar.io/snapchat/@teddysdaytoday](https://unavatar.io/snapchat/@teddysdaytoday)
|
|
402
|
-
|
|
403
506
|
### SoundCloud
|
|
404
507
|
|
|
405
508
|
Get any SoundCloud artist's profile picture by their username.
|
|
@@ -444,14 +547,6 @@ Available inputs:
|
|
|
444
547
|
|
|
445
548
|
- slug, e.g., [unavatar.io/telegram/drsdavidsoft](https://unavatar.io/telegram/drsdavidsoft)
|
|
446
549
|
|
|
447
|
-
### Threads
|
|
448
|
-
|
|
449
|
-
Get any Threads user's profile picture by their username.
|
|
450
|
-
|
|
451
|
-
Available inputs:
|
|
452
|
-
|
|
453
|
-
- slug, e.g., [unavatar.io/threads/zuck](https://unavatar.io/threads/zuck) or [unavatar.io/threads/@zuck](https://unavatar.io/threads/@zuck)
|
|
454
|
-
|
|
455
550
|
### TikTok
|
|
456
551
|
|
|
457
552
|
Get any TikTok user's profile picture by their username. No authentication or API tokens needed — just pass the username.
|
|
@@ -545,6 +640,18 @@ These headers help you understand pricing, limits, and request diagnostics.
|
|
|
545
640
|
| `x-rate-limit-reset` | UTC epoch seconds when window resets (free tier only) |
|
|
546
641
|
| `retry-after` | Seconds until rate limit resets (only on 429 responses) |
|
|
547
642
|
|
|
643
|
+
``` bash
|
|
644
|
+
$ curl -I -H "x-api-key: YOUR_API_KEY" https://[unavatar.io/github/kikobeats](https://unavatar.io/github/kikobeats)
|
|
645
|
+
|
|
646
|
+
x-pricing-tier: pro
|
|
647
|
+
x-timestamp: 1744209600
|
|
648
|
+
x-unavatar-cost: 1
|
|
649
|
+
x-proxy-tier: origin
|
|
650
|
+
x-rate-limit-limit: 50
|
|
651
|
+
x-rate-limit-remaining: 49
|
|
652
|
+
x-rate-limit-reset: 1744243200
|
|
653
|
+
```
|
|
654
|
+
|
|
548
655
|
Expected errors are known operational cases returned with stable codes.
|
|
549
656
|
|
|
550
657
|
- **Client-side issues** return `status: "fail"` (HTTP `4xx`).
|
|
@@ -573,11 +680,11 @@ Expected errors are known operational cases returned with stable codes.
|
|
|
573
680
|
| 409 | `EAPIKEYEXISTS` | Custom API key already exists |
|
|
574
681
|
| 409 | `EAPIKEYLABELEXISTS` | API key label already exists |
|
|
575
682
|
| 409 | `EAPIKEYMIN` | Attempt to remove last remaining key |
|
|
576
|
-
| 429 | `ERATE` |
|
|
683
|
+
| 429 | `ERATE` | Anonymous daily rate limit exceeded |
|
|
577
684
|
| 500 | `ECHECKOUT` | Stripe checkout session creation failed |
|
|
578
685
|
| 500 | `EAPIKEYFAILED` | API key retrieval after checkout failed |
|
|
579
686
|
| 500 | `EINTERNAL` | Unexpected internal server failure |
|
|
580
687
|
|
|
581
688
|
## Contact
|
|
582
689
|
|
|
583
|
-
If you have any suggestion or bug to report, please contact to ust mailing to [hello@unavatar.io](mailto:hello@unavatar.io).
|
|
690
|
+
If you have any suggestion or bug to report, please contact to ust mailing to [hello@unavatar.io](mailto:hello@unavatar.io).
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@unavatar/core",
|
|
3
3
|
"description": "Get unified user avatar from social networks, including Instagram, SoundCloud, Telegram, Twitter, YouTube & more.",
|
|
4
4
|
"homepage": "https://unavatar.io",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.14.1",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.js",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const getAvatarUrl = input => `https://www.behance.net/${input}`
|
|
4
|
+
|
|
5
|
+
module.exports = ({ createHtmlProvider, getOgImage }) =>
|
|
6
|
+
createHtmlProvider({
|
|
7
|
+
name: 'behance',
|
|
8
|
+
url: getAvatarUrl,
|
|
9
|
+
getter: getOgImage
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
module.exports.getAvatarUrl = getAvatarUrl
|
package/src/providers/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const providersBy = {
|
|
|
4
4
|
email: ['gravatar'],
|
|
5
5
|
username: [
|
|
6
6
|
'apple-music',
|
|
7
|
+
'behance',
|
|
7
8
|
'bluesky',
|
|
8
9
|
'deviantart',
|
|
9
10
|
'discord',
|
|
@@ -39,6 +40,7 @@ const providersBy = {
|
|
|
39
40
|
module.exports = ctx => {
|
|
40
41
|
const providers = {
|
|
41
42
|
'apple-music': require('./apple-music')(ctx),
|
|
43
|
+
behance: require('./behance')(ctx),
|
|
42
44
|
bluesky: require('./bluesky')(ctx),
|
|
43
45
|
deviantart: require('./deviantart')(ctx),
|
|
44
46
|
discord: require('./discord')(ctx),
|