emulating-user-agent 1.0.0__tar.gz
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.
- emulating_user_agent-1.0.0/Emulating/AndroidUserAgent.py +480 -0
- emulating_user_agent-1.0.0/Emulating/DeskTopUserAgent.py +52 -0
- emulating_user_agent-1.0.0/Emulating/UserAgentV6.py +454 -0
- emulating_user_agent-1.0.0/Emulating/__init__.py +0 -0
- emulating_user_agent-1.0.0/LICENSE +21 -0
- emulating_user_agent-1.0.0/PKG-INFO +124 -0
- emulating_user_agent-1.0.0/README.md +97 -0
- emulating_user_agent-1.0.0/emulating_user_agent.egg-info/PKG-INFO +124 -0
- emulating_user_agent-1.0.0/emulating_user_agent.egg-info/SOURCES.txt +11 -0
- emulating_user_agent-1.0.0/emulating_user_agent.egg-info/dependency_links.txt +1 -0
- emulating_user_agent-1.0.0/emulating_user_agent.egg-info/top_level.txt +1 -0
- emulating_user_agent-1.0.0/pyproject.toml +37 -0
- emulating_user_agent-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import random
|
|
2
|
+
|
|
3
|
+
from .DeskTopUserAgent import USER_AGENTS
|
|
4
|
+
from .UserAgentV6 import get_random_device, generate_barcelona_version
|
|
5
|
+
|
|
6
|
+
_ANDROID_CHROME_VERSIONS: list[str] = [
|
|
7
|
+
"145.0.7478.30", "146.0.7680.164"
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
LOCALES: list[tuple[str, str]] = [
|
|
11
|
+
("en_US", "en"), ("en_GB", "en"), ("fr_FR", "fr"), ("de_DE", "de"),
|
|
12
|
+
("es_ES", "es"), ("pt_BR", "pt"), ("it_IT", "it"), ("ja_JP", "ja"),
|
|
13
|
+
("ko_KR", "ko"), ("zh_CN", "zh"), ("zh_TW", "zh"), ("ar_SA", "ar"),
|
|
14
|
+
("ru_RU", "ru"), ("tr_TR", "tr"), ("nl_NL", "nl"), ("pl_PL", "pl"),
|
|
15
|
+
("sv_SE", "sv"), ("da_DK", "da"), ("nb_NO", "nb"), ("fi_FI", "fi"),
|
|
16
|
+
("id_ID", "id"), ("ms_MY", "ms"), ("th_TH", "th"), ("vi_VN", "vi"),
|
|
17
|
+
("hi_IN", "hi"), ("uk_UA", "uk"), ("ro_RO", "ro"), ("cs_CZ", "cs"),
|
|
18
|
+
("hu_HU", "hu"), ("el_GR", "el"),
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _locale(isEN: bool) -> tuple[str, str]:
|
|
23
|
+
if isEN:
|
|
24
|
+
return random.choice([("en_US", "en"),("en_GB", "en")])
|
|
25
|
+
return random.choice(LOCALES)
|
|
26
|
+
|
|
27
|
+
_ANDROID_BUILDS: dict[str, list[dict]] = {
|
|
28
|
+
"android_10": [ # Lancé en 2019
|
|
29
|
+
{"build": "QP1A.190711.019", "models": ["Pixel 2", "Pixel 3", "Pixel 4"]},
|
|
30
|
+
{"build": "QKQ1.190825.002", "models": ["Xiaomi Mi 9", "Redmi Note 8 Pro"]},
|
|
31
|
+
{"build": "G973FXXU3ASJG", "models": ["Galaxy S10", "Galaxy Note 10"]}, # Build Samsung One UI 2.0
|
|
32
|
+
],
|
|
33
|
+
"android_11": [ # Lancé en 2020
|
|
34
|
+
{"build": "RP1A.200720.009", "models": ["Pixel 3", "Pixel 4", "Pixel 5"]},
|
|
35
|
+
{"build": "RKQ1.200826.002", "models": ["Xiaomi Mi 10", "POCO F2 Pro"]},
|
|
36
|
+
{"build": "G980FXXU5CTKG", "models": ["Galaxy S20", "Galaxy Note 20"]}, # Build Samsung One UI 3.0
|
|
37
|
+
{"build": "RP1A.201005.001", "models": ["OnePlus 8", "OnePlus 8 Pro"]},
|
|
38
|
+
],
|
|
39
|
+
"google": [
|
|
40
|
+
{"build": "AP2A.240605.024", "models": ["Pixel 6", "Pixel 7", "Pixel 8"]},
|
|
41
|
+
{"build": "AP3A.240905.015", "models": ["Pixel 9", "Pixel 9 Pro"]},
|
|
42
|
+
{"build": "AP4A.250305.019", "models": ["Pixel 9a", "Pixel 10 Series"]},
|
|
43
|
+
{"build": "BP1A.250505.002", "models": ["Pixel 10 Pro", "Pixel Fold 2"]},
|
|
44
|
+
{"build": "BP2A.250605.012", "models": ["Pixel 10 Series (Beta Android 16)"]},
|
|
45
|
+
{"build": "CP1A.260305.018", "models": ["Pixel 11 (Early Preview 2026)"]},
|
|
46
|
+
],
|
|
47
|
+
"samsung": [
|
|
48
|
+
{"build": "UP1A.231005.007.A1", "models": ["Galaxy S23 Ultra", "Z Fold 5"]},
|
|
49
|
+
{"build": "AP2A.240905.003.A1", "models": ["Galaxy S24 Series", "Galaxy A55"]},
|
|
50
|
+
{"build": "AP3A.240905.015.A1", "models": ["Galaxy S25 Ultra", "Galaxy Z Flip 7"]},
|
|
51
|
+
{"build": "BP1A.250505.002.A1", "models": ["Galaxy S26 Series (2026)"]},
|
|
52
|
+
{"build": "S948BXXU3CXH7", "models": ["Galaxy S24"]},
|
|
53
|
+
],
|
|
54
|
+
"qcom": [ # Snapdragon — OnePlus, Xiaomi, OPPO, Sony, Asus, Nothing…
|
|
55
|
+
{"build": "SKQ1.211019.001", "models": ["Xiaomi 12", "OnePlus 10 Pro"]},
|
|
56
|
+
{"build": "UKQ1.230917.001", "models": ["Nothing Phone 2", "OPPO Find X7"]},
|
|
57
|
+
{"build": "UP1A.231005.007", "models": ["OnePlus 12", "Xiaomi 14"]},
|
|
58
|
+
{"build": "AP3A.240905.015", "models": ["Xiaomi 15", "OnePlus 13"]},
|
|
59
|
+
{"build": "BP1A.250505.002", "models": ["Xiaomi 16", "OnePlus 14 (2026)"]},
|
|
60
|
+
],
|
|
61
|
+
"mtk": [ # MediaTek Dimensity — OPPO, Vivo, Motorola, Redmi…
|
|
62
|
+
{"build": "SP1A.210812.016", "models": ["Redmi Note 11 Pro", "Vivo V23"]},
|
|
63
|
+
{"build": "TP1A.220624.014", "models": ["Redmi Note 12", "OPPO Reno 10"]},
|
|
64
|
+
{"build": "UP1A.231005.007", "models": ["Xiaomi 13T Pro", "OPPO Find X6"]},
|
|
65
|
+
{"build": "AP2A.240605.024", "models": ["Redmi Note 14 Pro+", "Dimensity 9300 models"]},
|
|
66
|
+
{"build": "BP1A.250505.005", "models": ["Xiaomi 15T", "OPPO Find X8 (2026)"]},
|
|
67
|
+
],
|
|
68
|
+
"exynos": [ # Samsung Exynos — Galaxy A/mid-range
|
|
69
|
+
{"build": "UP1A.231005.007.A1", "models": ["Galaxy A54", "Galaxy A34"]},
|
|
70
|
+
{"build": "AP2A.240905.003.A1", "models": ["Galaxy A55", "Galaxy A35"]},
|
|
71
|
+
{"build": "BP1A.250505.002.A1", "models": ["Galaxy A56 (2026)"]},
|
|
72
|
+
],
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _barcelona_version() -> str:
|
|
77
|
+
return generate_barcelona_version()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _timestamp() -> int:
|
|
81
|
+
return random.choice([922050745, 918016277, 925944384])
|
|
82
|
+
|
|
83
|
+
def _build_android_ua(model: str, build: str, android_version: str,
|
|
84
|
+
api_level: str, dpi: str, resolution: str,
|
|
85
|
+
manufacturer: str, codename: str, chipset: str,
|
|
86
|
+
locale: tuple | None) -> str:
|
|
87
|
+
|
|
88
|
+
lang_region, _ = locale if locale else _locale(True)
|
|
89
|
+
chrome = random.choice(_ANDROID_CHROME_VERSIONS)
|
|
90
|
+
bcn = _barcelona_version()
|
|
91
|
+
ts = _timestamp()
|
|
92
|
+
return (
|
|
93
|
+
f"Mozilla/5.0 (Linux; Android {android_version}; {model} Build/{build}; wv) "
|
|
94
|
+
f"AppleWebKit/537.36 (KHTML, like Gecko) "
|
|
95
|
+
f"Version/4.0 Chrome/{chrome} Mobile Safari/537.36 "
|
|
96
|
+
f"Barcelona {bcn} "
|
|
97
|
+
f"Android ({api_level}/{android_version}; {dpi}dpi; {resolution}; "
|
|
98
|
+
f"{manufacturer}; {model}; {codename}; {chipset}; {lang_region}; {ts})"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
103
|
+
_ANDROID_DEVICE_CONFIGS: dict[str, list[dict]] = {
|
|
104
|
+
|
|
105
|
+
# ── Samsung Galaxy S25 series (2025) ─────────────────────────
|
|
106
|
+
"Samsung Galaxy S25 Ultra": [{"model_pool": [("SM-S938B", "q6q"), ("SM-S938U", "q6q")],
|
|
107
|
+
"build_family": "samsung", "android_pool": [("15", "35"), ("16", "36")],
|
|
108
|
+
"dpi": "500", "resolution": "1440x3120", "viewport": (412, 917),
|
|
109
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
110
|
+
"Samsung Galaxy S25+": [{"model_pool": [("SM-S936B", "e3q"), ("SM-S936U", "e3q")],
|
|
111
|
+
"build_family": "samsung", "android_pool": [("15", "35"), ("16", "36")],
|
|
112
|
+
"dpi": "516", "resolution": "1440x3024", "viewport": (412, 904),
|
|
113
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
114
|
+
"Samsung Galaxy S25": [{"model_pool": [("SM-S931B", "e1q"), ("SM-S931U", "e1q")],
|
|
115
|
+
"build_family": "samsung", "android_pool": [("15", "35"), ("16", "36")],
|
|
116
|
+
"dpi": "416", "resolution": "1080x2340", "viewport": (360, 800),
|
|
117
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
118
|
+
|
|
119
|
+
# ── Samsung Galaxy S24 series (2024) ─────────────────────────
|
|
120
|
+
"Samsung Galaxy S24 Ultra": [{"model_pool": [("SM-S928B", "e2q"), ("SM-S928U", "e2q")],
|
|
121
|
+
"build_family": "samsung", "android_pool": [("14", "34"), ("15", "35")],
|
|
122
|
+
"dpi": "500", "resolution": "1440x3088", "viewport": (412, 915),
|
|
123
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
124
|
+
"Samsung Galaxy S24+": [{"model_pool": [("SM-S926B", "p6q"), ("SM-S926U", "p6q")],
|
|
125
|
+
"build_family": "samsung", "android_pool": [("14", "34"), ("15", "35")],
|
|
126
|
+
"dpi": "516", "resolution": "1440x3120", "viewport": (412, 917),
|
|
127
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
128
|
+
"Samsung Galaxy S24": [{"model_pool": [("SM-S921B", "e1q"), ("SM-S921U", "e1q")],
|
|
129
|
+
"build_family": "samsung", "android_pool": [("14", "34"), ("15", "35")],
|
|
130
|
+
"dpi": "416", "resolution": "1080x2340", "viewport": (360, 800),
|
|
131
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
132
|
+
|
|
133
|
+
# ── Samsung Galaxy S23 series (2023) ─────────────────────────
|
|
134
|
+
"Samsung Galaxy S23 Ultra": [{"model_pool": [("SM-S918B", "p3q"), ("SM-S918U", "p3q")],
|
|
135
|
+
"build_family": "samsung", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
136
|
+
"dpi": "500", "resolution": "1440x3088", "viewport": (412, 915),
|
|
137
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
138
|
+
"Samsung Galaxy S23": [{"model_pool": [("SM-S911B", "dm1q"), ("SM-S911U", "dm1q")],
|
|
139
|
+
"build_family": "samsung", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
140
|
+
"dpi": "425", "resolution": "1080x2340", "viewport": (360, 780),
|
|
141
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
142
|
+
|
|
143
|
+
# ── Samsung Galaxy A series ───────────────────────────────────
|
|
144
|
+
"Samsung Galaxy A55": [{"model_pool": [("SM-A556B", "a55x")],
|
|
145
|
+
"build_family": "samsung", "android_pool": [("14", "34"), ("15", "35")],
|
|
146
|
+
"dpi": "390", "resolution": "1080x2340", "viewport": (360, 800),
|
|
147
|
+
"manufacturer": "samsung", "chipset": "exynos", "locale": None}],
|
|
148
|
+
"Samsung Galaxy A35": [{"model_pool": [("SM-A356B", "a35x")],
|
|
149
|
+
"build_family": "samsung", "android_pool": [("14", "34"), ("15", "35")],
|
|
150
|
+
"dpi": "390", "resolution": "1080x2340", "viewport": (360, 800),
|
|
151
|
+
"manufacturer": "samsung", "chipset": "exynos", "locale": None}],
|
|
152
|
+
|
|
153
|
+
# ── Google Pixel 9 series (2024) ─────────────────────────────
|
|
154
|
+
"Google Pixel 9 Pro XL": [{"model_pool": [("Pixel 9 Pro XL", "tokay")],
|
|
155
|
+
"build_family": "google", "android_pool": [("15", "35"), ("16", "36")],
|
|
156
|
+
"dpi": "486", "resolution": "1344x2992", "viewport": (412, 915),
|
|
157
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
158
|
+
"Google Pixel 9 Pro": [{"model_pool": [("Pixel 9 Pro", "caiman")],
|
|
159
|
+
"build_family": "google", "android_pool": [("15", "35"), ("16", "36")],
|
|
160
|
+
"dpi": "474", "resolution": "1280x2856", "viewport": (393, 875),
|
|
161
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
162
|
+
"Google Pixel 9": [{"model_pool": [("Pixel 9", "komodo")],
|
|
163
|
+
"build_family": "google", "android_pool": [("15", "35"), ("16", "36")],
|
|
164
|
+
"dpi": "422", "resolution": "1080x2424", "viewport": (393, 851),
|
|
165
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
166
|
+
"Google Pixel 9 Pro Fold": [{"model_pool": [("Pixel 9 Pro Fold", "comet")],
|
|
167
|
+
"build_family": "google", "android_pool": [("15", "35"), ("16", "36")],
|
|
168
|
+
"dpi": "380", "resolution": "2076x2152", "viewport": (600, 624),
|
|
169
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
170
|
+
|
|
171
|
+
# ── Google Pixel 8 series (2023) ─────────────────────────────
|
|
172
|
+
"Google Pixel 8 Pro": [{"model_pool": [("Pixel 8 Pro", "husky")],
|
|
173
|
+
"build_family": "google", "android_pool": [("14", "34"), ("15", "35")],
|
|
174
|
+
"dpi": "489", "resolution": "1344x2992", "viewport": (412, 915),
|
|
175
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
176
|
+
"Google Pixel 8": [{"model_pool": [("Pixel 8", "shiba")],
|
|
177
|
+
"build_family": "google", "android_pool": [("14", "34"), ("15", "35")],
|
|
178
|
+
"dpi": "428", "resolution": "1080x2400", "viewport": (393, 851),
|
|
179
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
180
|
+
"Google Pixel 7a": [{"model_pool": [("Pixel 7a", "lynx")],
|
|
181
|
+
"build_family": "google", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
182
|
+
"dpi": "429", "resolution": "1080x2400", "viewport": (393, 851),
|
|
183
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
184
|
+
|
|
185
|
+
# ── OnePlus (2024/2025) ───────────────────────────────────────
|
|
186
|
+
"OnePlus 13": [{"model_pool": [("CPH2687", "op13"), ("PJZ110", "op13")],
|
|
187
|
+
"build_family": "qcom", "android_pool": [("15", "35"), ("16", "36")],
|
|
188
|
+
"dpi": "450", "resolution": "1440x3168", "viewport": (412, 915),
|
|
189
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
190
|
+
"OnePlus 12": [{"model_pool": [("CPH2583", "op12"), ("PJX110", "op12")],
|
|
191
|
+
"build_family": "qcom", "android_pool": [("14", "34"), ("15", "35")],
|
|
192
|
+
"dpi": "450", "resolution": "1440x3168", "viewport": (412, 915),
|
|
193
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
194
|
+
"OnePlus 13R": [{"model_pool": [("CPH2641", "op13r")],
|
|
195
|
+
"build_family": "qcom", "android_pool": [("14", "34"), ("15", "35")],
|
|
196
|
+
"dpi": "388", "resolution": "1080x2392", "viewport": (393, 851),
|
|
197
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
198
|
+
"OnePlus Nord 4": [{"model_pool": [("CPH2657", "opnord4")],
|
|
199
|
+
"build_family": "qcom", "android_pool": [("14", "34"), ("15", "35")],
|
|
200
|
+
"dpi": "450", "resolution": "1240x2772", "viewport": (412, 900),
|
|
201
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
202
|
+
|
|
203
|
+
# ── Xiaomi (2023/2024/2025) ───────────────────────────────────
|
|
204
|
+
"Xiaomi 15": [{"model_pool": [("25030PN0DG", "dada"), ("2501129G", "dada")],
|
|
205
|
+
"build_family": "qcom", "android_pool": [("15", "35"), ("16", "36")],
|
|
206
|
+
"dpi": "522", "resolution": "1440x3200", "viewport": (393, 873),
|
|
207
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
208
|
+
"Xiaomi 14 Pro": [{"model_pool": [("23116PN5BC", "shennong")],
|
|
209
|
+
"build_family": "qcom", "android_pool": [("14", "34"), ("15", "35")],
|
|
210
|
+
"dpi": "522", "resolution": "1440x3200", "viewport": (393, 873),
|
|
211
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
212
|
+
"Xiaomi 14": [{"model_pool": [("23127PN0CG", "houji"), ("23116PN5BC", "houji")],
|
|
213
|
+
"build_family": "qcom", "android_pool": [("14", "34"), ("15", "35")],
|
|
214
|
+
"dpi": "460", "resolution": "1200x2670", "viewport": (393, 873),
|
|
215
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
216
|
+
"Redmi Note 14 Pro+": [{"model_pool": [("24116RA68G", "opal")],
|
|
217
|
+
"build_family": "qcom", "android_pool": [("14", "34"), ("15", "35")],
|
|
218
|
+
"dpi": "446", "resolution": "1220x2712", "viewport": (393, 873),
|
|
219
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
220
|
+
|
|
221
|
+
# ── OPPO / realme (2023/2024) ────────────────────────────────
|
|
222
|
+
"OPPO Find X8 Pro": [{"model_pool": [("CPH2637", "OP6F29L1"), ("CPH2639", "OP6F29L1")],
|
|
223
|
+
"build_family": "mtk", "android_pool": [("15", "35")],
|
|
224
|
+
"dpi": "450", "resolution": "1264x2780", "viewport": (412, 900),
|
|
225
|
+
"manufacturer": "OPPO", "chipset": "mtk", "locale": None}],
|
|
226
|
+
"OPPO Find X6 Pro": [{"model_pool": [("PGEM10", "OP4EBF")],
|
|
227
|
+
"build_family": "mtk", "android_pool": [("13", "33"), ("14", "34")],
|
|
228
|
+
"dpi": "450", "resolution": "1440x3168", "viewport": (412, 915),
|
|
229
|
+
"manufacturer": "OPPO", "chipset": "mtk", "locale": None}],
|
|
230
|
+
"realme GT 7 Pro": [{"model_pool": [("RMX3999", "RE5E35L1")],
|
|
231
|
+
"build_family": "qcom", "android_pool": [("15", "35")],
|
|
232
|
+
"dpi": "450", "resolution": "1264x2780", "viewport": (412, 900),
|
|
233
|
+
"manufacturer": "realme", "chipset": "qcom", "locale": None}],
|
|
234
|
+
"realme GT 6": [{"model_pool": [("RMX3851", "RE5C38L1")],
|
|
235
|
+
"build_family": "qcom", "android_pool": [("14", "34"), ("15", "35")],
|
|
236
|
+
"dpi": "510", "resolution": "1440x3168", "viewport": (412, 915),
|
|
237
|
+
"manufacturer": "realme", "chipset": "qcom", "locale": None}],
|
|
238
|
+
|
|
239
|
+
# ── Samsung Galaxy Z series (2023) ───────────────────────────
|
|
240
|
+
"Samsung Galaxy Z Fold5": [{"model_pool": [("SM-F946B", "q4q"), ("SM-F946U", "q4q")],
|
|
241
|
+
"build_family": "samsung", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
242
|
+
# Écran intérieur déplié : 2176×1812 @374dpi — viewport CSS plié/déplié
|
|
243
|
+
"dpi": "374", "resolution": "2176x1812", "viewport": (768, 1080),
|
|
244
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
245
|
+
"Samsung Galaxy Z Flip5": [{"model_pool": [("SM-F731B", "b4q"), ("SM-F731U", "b4q")],
|
|
246
|
+
"build_family": "samsung", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
247
|
+
"dpi": "424", "resolution": "1080x2640", "viewport": (412, 876),
|
|
248
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
249
|
+
|
|
250
|
+
# ── Samsung Galaxy A54 (2023) ────────────────────────────────
|
|
251
|
+
"Samsung Galaxy A54": [{"model_pool": [("SM-A546B", "a54x")],
|
|
252
|
+
"build_family": "exynos", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
253
|
+
"dpi": "390", "resolution": "1080x2340", "viewport": (360, 780),
|
|
254
|
+
"manufacturer": "samsung", "chipset": "exynos", "locale": None}],
|
|
255
|
+
|
|
256
|
+
# ── Google Pixel 7 series (2022) ─────────────────────────────
|
|
257
|
+
"Google Pixel 7 Pro": [{"model_pool": [("Pixel 7 Pro", "cheetah")],
|
|
258
|
+
"build_family": "google", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
259
|
+
"dpi": "512", "resolution": "1440x3120", "viewport": (412, 892),
|
|
260
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
261
|
+
"Google Pixel 7": [{"model_pool": [("Pixel 7", "panther")],
|
|
262
|
+
"build_family": "google", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
263
|
+
"dpi": "429", "resolution": "1080x2400", "viewport": (412, 915),
|
|
264
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
265
|
+
"Google Pixel 6a": [{"model_pool": [("Pixel 6a", "bluejay")],
|
|
266
|
+
"build_family": "google", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
267
|
+
"dpi": "429", "resolution": "1080x2400", "viewport": (412, 892),
|
|
268
|
+
"manufacturer": "Google", "chipset": "google", "locale": None}],
|
|
269
|
+
|
|
270
|
+
# ── OnePlus 11 / Nord 3 (2023) ───────────────────────────────
|
|
271
|
+
"OnePlus 11": [{"model_pool": [("CPH2449", "salami"), ("PHB110", "salami")],
|
|
272
|
+
"build_family": "qcom", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
273
|
+
"dpi": "500", "resolution": "1440x3216", "viewport": (412, 915),
|
|
274
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
275
|
+
"OnePlus Nord 3": [{"model_pool": [("CPH2491", "opnord3")],
|
|
276
|
+
"build_family": "mtk", "android_pool": [("13", "33"), ("14", "34")],
|
|
277
|
+
"dpi": "394", "resolution": "1080x2424", "viewport": (393, 851),
|
|
278
|
+
"manufacturer": "OnePlus", "chipset": "mtk", "locale": None}],
|
|
279
|
+
|
|
280
|
+
# ── Xiaomi 13 / Redmi Note 13 Pro (2022/2023) ────────────────
|
|
281
|
+
"Xiaomi 13": [{"model_pool": [("2211133C", "fuxi"), ("2210132C", "fuxi")],
|
|
282
|
+
"build_family": "qcom", "android_pool": [("13", "33"), ("14", "34")],
|
|
283
|
+
"dpi": "422", "resolution": "1080x2400", "viewport": (393, 851),
|
|
284
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
285
|
+
"Redmi Note 13 Pro": [{"model_pool": [("23124RN87C", "garnet")],
|
|
286
|
+
# 23124RN87C = Redmi Note 13 Pro+ 5G (Snapdragon 7s Gen 2)
|
|
287
|
+
"build_family": "qcom", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
288
|
+
"dpi": "446", "resolution": "1220x2712", "viewport": (393, 873),
|
|
289
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
290
|
+
|
|
291
|
+
# ── Vivo X90 Pro (2022) ──────────────────────────────────────
|
|
292
|
+
"Vivo X90 Pro": [{"model_pool": [("V2227A", "pd2217")],
|
|
293
|
+
"build_family": "mtk", "android_pool": [("13", "33"), ("14", "34")],
|
|
294
|
+
"dpi": "450", "resolution": "1260x2800", "viewport": (412, 915),
|
|
295
|
+
"manufacturer": "vivo", "chipset": "mtk", "locale": None}],
|
|
296
|
+
|
|
297
|
+
# ── Huawei P60 Pro (2023) ────────────────────────────────────
|
|
298
|
+
"Huawei P60 Pro": [{"model_pool": [("ALN-AL00", "alnp")],
|
|
299
|
+
# HarmonyOS 3.1/4.0 — Android 12/13 base, Kirin 9000S
|
|
300
|
+
"build_family": "qcom", "android_pool": [("12", "32"), ("13", "33")],
|
|
301
|
+
"dpi": "448", "resolution": "1220x2700", "viewport": (393, 873),
|
|
302
|
+
"manufacturer": "HUAWEI", "chipset": "qcom", "locale": None}],
|
|
303
|
+
|
|
304
|
+
# ── Motorola Edge 40 Pro (2023) ──────────────────────────────
|
|
305
|
+
"Motorola Edge 40 Pro": [{"model_pool": [("motorola edge 40 pro", "dubai")],
|
|
306
|
+
"build_family": "mtk", "android_pool": [("13", "33"), ("14", "34")],
|
|
307
|
+
"dpi": "360", "resolution": "1080x2400", "viewport": (393, 851),
|
|
308
|
+
"manufacturer": "motorola", "chipset": "mtk", "locale": None}],
|
|
309
|
+
|
|
310
|
+
# ── Sony Xperia 1 V (2023) ───────────────────────────────────
|
|
311
|
+
"Sony Xperia 1 V": [{"model_pool": [("XQ-DQ72", "pdx234")],
|
|
312
|
+
# Dalle 4K 21:9 — 3840×1644 @643ppi ; Android reporte généralement ~240dpi logique
|
|
313
|
+
"build_family": "qcom", "android_pool": [("13", "33"), ("14", "34")],
|
|
314
|
+
"dpi": "643", "resolution": "3840x1644", "viewport": (412, 915),
|
|
315
|
+
"manufacturer": "Sony", "chipset": "qcom", "locale": None}],
|
|
316
|
+
|
|
317
|
+
# ── Asus ROG Phone 7 (2023) ──────────────────────────────────
|
|
318
|
+
"Asus ROG Phone 7": [{"model_pool": [("ASUS_AI2205", "AI2205")],
|
|
319
|
+
"build_family": "qcom", "android_pool": [("13", "33"), ("14", "34")],
|
|
320
|
+
"dpi": "394", "resolution": "1080x2448", "viewport": (393, 851),
|
|
321
|
+
"manufacturer": "Asus", "chipset": "qcom", "locale": None}],
|
|
322
|
+
|
|
323
|
+
# ── Nothing Phone 2 (2023) ───────────────────────────────────
|
|
324
|
+
"Nothing Phone 2": [{"model_pool": [("A065", "Pong")],
|
|
325
|
+
"build_family": "qcom", "android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
326
|
+
"dpi": "394", "resolution": "1080x2412", "viewport": (393, 851),
|
|
327
|
+
"manufacturer": "Nothing", "chipset": "qcom", "locale": None}],
|
|
328
|
+
|
|
329
|
+
# ── Tablettes Android ─────────────────────────────────────────
|
|
330
|
+
"Samsung Galaxy Tab S9 Ultra": [{"model_pool": [("SM-X916B", "gts9u"), ("SM-X916U", "gts9u")],
|
|
331
|
+
"build_family": "samsung",
|
|
332
|
+
"android_pool": [("13", "33"), ("14", "34"), ("15", "35")],
|
|
333
|
+
# 14.6" QHD+ 2960×1848 @240ppi — viewport CSS logique @2x
|
|
334
|
+
"dpi": "240", "resolution": "1848x2960", "viewport": (924, 1480),
|
|
335
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
336
|
+
"Samsung Galaxy Tab S8": [{"model_pool": [("SM-X706B", "gts8p")],
|
|
337
|
+
"build_family": "samsung", "android_pool": [("12", "32"), ("13", "33"), ("14", "34")],
|
|
338
|
+
# 11" WQXGA 2560×1600 @274ppi
|
|
339
|
+
"dpi": "274", "resolution": "1600x2560", "viewport": (800, 1280),
|
|
340
|
+
"manufacturer": "samsung", "chipset": "qcom", "locale": None}],
|
|
341
|
+
|
|
342
|
+
# ── Google Pixel (Anciennes Générations) ─────────────────────────
|
|
343
|
+
"Google Pixel 5": [{"model_pool": [("Pixel 5", "redfin")],
|
|
344
|
+
"build_family": "android_11", "android_pool": [("11", "30"), ("12", "31"), ("13", "33")],
|
|
345
|
+
"dpi": "432", "resolution": "1080x2340", "viewport": (393, 851),
|
|
346
|
+
"manufacturer": "Google", "chipset": "qcom", "locale": None}],
|
|
347
|
+
"Google Pixel 4": [{"model_pool": [("Pixel 4", "flame"), ("Pixel 4 XL", "coral")],
|
|
348
|
+
"build_family": "android_10", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
349
|
+
"dpi": "444", "resolution": "1080x2280", "viewport": (393, 830),
|
|
350
|
+
"manufacturer": "Google", "chipset": "qcom", "locale": None}],
|
|
351
|
+
"Google Pixel 3": [{"model_pool": [("Pixel 3", "blueline"), ("Pixel 3 XL", "crosshatch")],
|
|
352
|
+
"build_family": "android_10", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
353
|
+
"dpi": "443", "resolution": "1080x2160", "viewport": (393, 786),
|
|
354
|
+
"manufacturer": "Google", "chipset": "qcom", "locale": None}],
|
|
355
|
+
"Google Pixel 2": [{"model_pool": [("Pixel 2", "walleye"), ("Pixel 2 XL", "taimen")],
|
|
356
|
+
"build_family": "android_10", "android_pool": [("10", "29"), ("11", "30")],
|
|
357
|
+
"dpi": "416", "resolution": "1080x1920", "viewport": (411, 731),
|
|
358
|
+
"manufacturer": "Google", "chipset": "qcom", "locale": None}],
|
|
359
|
+
|
|
360
|
+
# ── Samsung Galaxy (Générations S10/S20/Note) ────────────────────
|
|
361
|
+
"Samsung Galaxy S20": [{"model_pool": [("SM-G980F", "x1s"), ("SM-G981B", "x1q")],
|
|
362
|
+
"build_family": "android_11", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
363
|
+
"dpi": "563", "resolution": "1440x3200", "viewport": (360, 800),
|
|
364
|
+
"manufacturer": "samsung", "chipset": "exynos", "locale": None}],
|
|
365
|
+
"Samsung Galaxy Note 20": [{"model_pool": [("SM-N980F", "c1s"), ("SM-N981B", "c1q")],
|
|
366
|
+
"build_family": "android_11", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
367
|
+
"dpi": "393", "resolution": "1080x2400", "viewport": (360, 800),
|
|
368
|
+
"manufacturer": "samsung", "chipset": "exynos", "locale": None}],
|
|
369
|
+
"Samsung Galaxy S10": [{"model_pool": [("SM-G973F", "beyond1"), ("SM-G973U", "beyond1q")],
|
|
370
|
+
"build_family": "android_10", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
371
|
+
"dpi": "550", "resolution": "1440x3040", "viewport": (360, 760),
|
|
372
|
+
"manufacturer": "samsung", "chipset": "exynos", "locale": None}],
|
|
373
|
+
"Samsung Galaxy Note 10": [{"model_pool": [("SM-N970F", "d1"), ("SM-N970U", "d1q")],
|
|
374
|
+
"build_family": "android_10", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
375
|
+
"dpi": "401", "resolution": "1080x2280", "viewport": (360, 760),
|
|
376
|
+
"manufacturer": "samsung", "chipset": "exynos", "locale": None}],
|
|
377
|
+
|
|
378
|
+
# ── Xiaomi / POCO / Redmi (Anciennes Générations) ────────────────
|
|
379
|
+
"Xiaomi Mi 10": [{"model_pool": [("M2001J2G", "umi")],
|
|
380
|
+
"build_family": "android_11", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
381
|
+
"dpi": "386", "resolution": "1080x2340", "viewport": (393, 851),
|
|
382
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
383
|
+
"Xiaomi Mi 9": [{"model_pool": [("M1902F1G", "cepheus")],
|
|
384
|
+
"build_family": "android_10", "android_pool": [("10", "29"), ("11", "30")],
|
|
385
|
+
"dpi": "403", "resolution": "1080x2340", "viewport": (393, 851),
|
|
386
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
387
|
+
"POCO F2 Pro": [{"model_pool": [("M2004J11G", "lmi")],
|
|
388
|
+
"build_family": "android_11", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
389
|
+
"dpi": "395", "resolution": "1080x2400", "viewport": (393, 851),
|
|
390
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
391
|
+
"Redmi Note 8 Pro": [{"model_pool": [("M1906G7G", "begonia")],
|
|
392
|
+
"build_family": "android_10", "android_pool": [("10", "29"), ("11", "30")],
|
|
393
|
+
"dpi": "395", "resolution": "1080x2340", "viewport": (393, 851),
|
|
394
|
+
"manufacturer": "Xiaomi", "chipset": "mtk", "locale": None}],
|
|
395
|
+
|
|
396
|
+
# ── OnePlus (Anciennes Générations) ──────────────────────────────
|
|
397
|
+
"OnePlus 8 Pro": [{"model_pool": [("IN2023", "instantnoodle")],
|
|
398
|
+
"build_family": "android_11", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
399
|
+
"dpi": "513", "resolution": "1440x3168", "viewport": (412, 906),
|
|
400
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
401
|
+
"OnePlus 8": [{"model_pool": [("IN2013", "galilei")],
|
|
402
|
+
"build_family": "android_11", "android_pool": [("10", "29"), ("11", "30"), ("12", "31")],
|
|
403
|
+
"dpi": "402", "resolution": "1080x2400", "viewport": (412, 915),
|
|
404
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
405
|
+
|
|
406
|
+
# ── Autres Modèles Récents (QCOM / MTK) ──────────────────────────
|
|
407
|
+
"Xiaomi 16": [{"model_pool": [("25127PN0CG", "xiaomi16")],
|
|
408
|
+
"build_family": "qcom", "android_pool": [("15", "35"), ("16", "36")],
|
|
409
|
+
"dpi": "460", "resolution": "1200x2670", "viewport": (393, 873),
|
|
410
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
411
|
+
"Xiaomi 15T": [{"model_pool": [("250720CG", "dugou")],
|
|
412
|
+
"build_family": "mtk", "android_pool": [("15", "35"), ("16", "36")],
|
|
413
|
+
"dpi": "446", "resolution": "1220x2712", "viewport": (393, 873),
|
|
414
|
+
"manufacturer": "Xiaomi", "chipset": "mtk", "locale": None}],
|
|
415
|
+
"Xiaomi 12": [{"model_pool": [("2201123G", "cupid")],
|
|
416
|
+
"build_family": "qcom", "android_pool": [("12", "32"), ("13", "33")],
|
|
417
|
+
"dpi": "419", "resolution": "1080x2400", "viewport": (393, 851),
|
|
418
|
+
"manufacturer": "Xiaomi", "chipset": "qcom", "locale": None}],
|
|
419
|
+
"OnePlus 10 Pro": [{"model_pool": [("NE2213", "ne2213")],
|
|
420
|
+
"build_family": "qcom", "android_pool": [("12", "32"), ("13", "33")],
|
|
421
|
+
"dpi": "525", "resolution": "1440x3216", "viewport": (412, 915),
|
|
422
|
+
"manufacturer": "OnePlus", "chipset": "qcom", "locale": None}],
|
|
423
|
+
"Redmi Note 11 Pro": [{"model_pool": [("2201116TG", "viva")],
|
|
424
|
+
"build_family": "mtk", "android_pool": [("11", "30"), ("12", "32")],
|
|
425
|
+
"dpi": "395", "resolution": "1080x2400", "viewport": (393, 851),
|
|
426
|
+
"manufacturer": "Xiaomi", "chipset": "mtk", "locale": None}],
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
# ── API Android ───────────────────────────────────────────────────────────────
|
|
431
|
+
|
|
432
|
+
def get_android_user_agent(isEN: bool, device_name: str | None = None) -> dict:
|
|
433
|
+
|
|
434
|
+
if device_name is None:
|
|
435
|
+
device_name = random.choice(list(_ANDROID_DEVICE_CONFIGS.keys()))
|
|
436
|
+
|
|
437
|
+
if device_name not in _ANDROID_DEVICE_CONFIGS:
|
|
438
|
+
raise ValueError(
|
|
439
|
+
f"Appareil Android '{device_name}' introuvable.\n"
|
|
440
|
+
f"Disponibles : {list_android_devices()}"
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
cfg = random.choice(_ANDROID_DEVICE_CONFIGS[device_name])
|
|
444
|
+
model, codename = random.choice(cfg["model_pool"])
|
|
445
|
+
build = random.choice(_ANDROID_BUILDS[cfg["build_family"]])["build"]
|
|
446
|
+
android_version, api_level = random.choice(cfg["android_pool"])
|
|
447
|
+
locale = cfg["locale"] if cfg["locale"] else _locale(isEN)
|
|
448
|
+
|
|
449
|
+
return {
|
|
450
|
+
"ua": _build_android_ua(model, build, android_version, api_level,
|
|
451
|
+
cfg["dpi"], cfg["resolution"],
|
|
452
|
+
cfg["manufacturer"], codename,
|
|
453
|
+
cfg["chipset"], locale),
|
|
454
|
+
"viewport": cfg["viewport"],
|
|
455
|
+
"mobile": True,
|
|
456
|
+
"locale": locale,
|
|
457
|
+
"android": android_version,
|
|
458
|
+
"model": model,
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def get_random_android_device(isEn: bool) -> tuple[str, dict]:
|
|
463
|
+
name = random.choice(list(_ANDROID_DEVICE_CONFIGS.keys()))
|
|
464
|
+
return name, get_android_user_agent(isEn, name)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def list_android_devices() -> list[str]:
|
|
468
|
+
return list(_ANDROID_DEVICE_CONFIGS.keys())
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def get_random_agent(isEn: bool) -> tuple:
|
|
472
|
+
val = random.random()
|
|
473
|
+
print(val)
|
|
474
|
+
if val < 0.51:
|
|
475
|
+
return get_random_device(isEn=isEn)
|
|
476
|
+
elif val < 0.9:
|
|
477
|
+
return get_random_android_device(isEn=isEn)
|
|
478
|
+
else:
|
|
479
|
+
return random.choice(list(USER_AGENTS.items()))
|
|
480
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
USER_AGENTS = {
|
|
2
|
+
# ── Windows 11 (Avril 2026) ──────────────────────────────────────
|
|
3
|
+
"Windows 11 - Chrome": {
|
|
4
|
+
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
5
|
+
"viewport": (1920, 1046),
|
|
6
|
+
"mobile": False
|
|
7
|
+
},
|
|
8
|
+
"Windows 11 - Edge": {
|
|
9
|
+
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0",
|
|
10
|
+
"viewport": (1920, 1046),
|
|
11
|
+
"mobile": False
|
|
12
|
+
},
|
|
13
|
+
"Windows 11 - Firefox": {
|
|
14
|
+
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0",
|
|
15
|
+
"viewport": (1920, 1046),
|
|
16
|
+
"mobile": False
|
|
17
|
+
},
|
|
18
|
+
"Windows 10 - Chrome": {
|
|
19
|
+
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
|
20
|
+
"viewport": (1536, 864),
|
|
21
|
+
"mobile": False
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
# ── macOS Sequoia 15.4 / Sonoma 14.7 (Avril 2026) ────────────────
|
|
25
|
+
"MacBook Pro M4 - Safari": {
|
|
26
|
+
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.4 Safari/605.1.15",
|
|
27
|
+
"viewport": (1728, 1116),
|
|
28
|
+
"mobile": False
|
|
29
|
+
},
|
|
30
|
+
"MacBook Pro M3 - Chrome": {
|
|
31
|
+
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
32
|
+
"viewport": (1728, 1116),
|
|
33
|
+
"mobile": False
|
|
34
|
+
},
|
|
35
|
+
"MacBook Air M3 - Safari": {
|
|
36
|
+
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.4 Safari/605.1.15",
|
|
37
|
+
"viewport": (1440, 893),
|
|
38
|
+
"mobile": False
|
|
39
|
+
},
|
|
40
|
+
"MacBook Air M3 - Chrome": {
|
|
41
|
+
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
42
|
+
"viewport": (1440, 893),
|
|
43
|
+
"mobile": False
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
# ── iMac / Studio (2026) ─────────────────────────────────────────
|
|
47
|
+
"iMac M4 24 - Safari": {
|
|
48
|
+
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.4 Safari/605.1.15",
|
|
49
|
+
"viewport": (2560, 1664),
|
|
50
|
+
"mobile": False
|
|
51
|
+
},
|
|
52
|
+
}
|