├── .eslintrc ├── src ├── index.ts ├── endpoints │ ├── top-charts.ts │ ├── search.ts │ └── app-details.ts └── common │ ├── app-meta.ts │ └── consts.ts ├── tsconfig.json ├── LICENSE ├── package.json ├── .gitignore ├── README.md └── docs └── README.md /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["@baltpeter/eslint-config"], 4 | "rules": { 5 | "no-console": "error" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './common/app-meta'; 2 | export * from './common/consts'; 3 | export * from './endpoints/app-details'; 4 | export * from './endpoints/search'; 5 | export * from './endpoints/top-charts'; 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@baltpeter/tsconfig", 3 | "include": ["src/**/*"], 4 | "typedocOptions": { 5 | "plugin": ["typedoc-plugin-markdown"], 6 | "entryPoints": ["src/index.ts"], 7 | "out": "docs", 8 | "readme": "none", 9 | "excludeNotDocumented": true, 10 | "includeVersion": false, 11 | "githubPages": false, 12 | "gitRevision": "main" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2023 Benjamin Altpeter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parse-tunes", 3 | "version": "1.1.0", 4 | "description": "Library for fetching select data on iOS apps from the Apple Apple Store via undocumented internal iTunes APIs.", 5 | "bugs": "https://github.com/tweaselORG/parse-tunes/issues", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tweaselORG/parse-tunes.git" 9 | }, 10 | "license": "MIT", 11 | "author": "Benjamin Altpeter ", 12 | "type": "module", 13 | "main": "dist/index.js", 14 | "source": "src/index.ts", 15 | "types": "dist/index.d.ts", 16 | "files": [ 17 | "/dist" 18 | ], 19 | "scripts": { 20 | "build": "parcel build", 21 | "fix": "yarn eslint . --ignore-path .gitignore --ext .js,.jsx,.ts,.tsx --fix", 22 | "lint": "tsc && eslint . --ignore-path .gitignore --ext .js,.jsx,.ts,.tsx && git diff --check", 23 | "prepack": "rm -rf .parcel-cache dist && yarn build && yarn typedoc", 24 | "test": "echo 'TODO: No tests specified yet.'", 25 | "watch": "parcel watch" 26 | }, 27 | "husky": { 28 | "hooks": { 29 | "pre-commit": "lint-staged && tsc && typedoc && git add docs" 30 | } 31 | }, 32 | "lint-staged": { 33 | "*.{ts,js,tsx,jsx,css,scss,json}": [ 34 | "prettier --write" 35 | ], 36 | "*.{ts,js,tsx,jsx}": [ 37 | "eslint --fix" 38 | ] 39 | }, 40 | "prettier": "@baltpeter/prettier-config", 41 | "dependencies": { 42 | "cross-fetch": "^3.1.5" 43 | }, 44 | "devDependencies": { 45 | "@baltpeter/eslint-config": "^2.1.0", 46 | "@baltpeter/prettier-config": "2.0.0", 47 | "@baltpeter/tsconfig": "^2.0.0", 48 | "@parcel/packager-ts": "2.8.2", 49 | "@parcel/transformer-typescript-types": "2.8.2", 50 | "@typescript-eslint/eslint-plugin": "5.48.0", 51 | "eslint": "8.31.0", 52 | "eslint-plugin-eslint-comments": "3.2.0", 53 | "eslint-plugin-import": "2.26.0", 54 | "husky": "4.3.7", 55 | "lint-staged": "13.1.0", 56 | "parcel": "2.8.2", 57 | "prettier": "2.8.2", 58 | "type-fest": "^3.5.3", 59 | "typedoc": "0.23.24", 60 | "typedoc-plugin-markdown": "3.14.0", 61 | "typescript": "4.9.4" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/endpoints/top-charts.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'cross-fetch'; 2 | import type { Genre, StorefrontCountry } from '../common/consts'; 3 | 4 | /** 5 | * The App Store top charts that can be fetched. 6 | * 7 | * @see https://github.com/tweaselORG/parse-tunes/issues/2#issuecomment-1377239436 8 | */ 9 | export const charts = { 10 | topFreeIphone: 27, 11 | topPaidIphone: 30, 12 | topGrossingIphone: 38, 13 | topFreeIpad: 44, 14 | topPaidIpad: 45, 15 | topGrossingIpad: 46, 16 | } as const; 17 | /** The `popId` of a chart on the App Store. */ 18 | export type Chart = (typeof charts)[keyof typeof charts]; 19 | 20 | /** Parameters for a top chart request. */ 21 | export type TopChartRequest = { 22 | /** The genre (category) for which to fetch the top apps. @see {@link genres} */ 23 | genre: Genre; 24 | /** The chart of top apps to fetch. @see {@link charts} */ 25 | chart: Chart; 26 | /** The country for which to fetch the respective top chart. @see {@link countries} */ 27 | country: StorefrontCountry; 28 | }; 29 | 30 | /** A list of the app IDs of the apps on the requested top chart. */ 31 | export type TopChartResult = string[]; 32 | 33 | export const topAppsApiUrl = (genreId: Genre, chartId: Chart) => 34 | `https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewTop?genreId=${genreId}&popId=${chartId}`; 35 | 36 | /** 37 | * Fetch the app IDs of the top apps in a given top chart. 38 | * 39 | * @param request The parameters for which top chart to fetch. 40 | * 41 | * @returns A list of numerical app IDs in the requested top chart. The list is sorted by rank. Currently always has 200 42 | * items. 43 | */ 44 | export async function fetchTopApps(request: TopChartRequest): Promise { 45 | // Depending on the platform set in the `X-Apple-Store-Front` header, Apple returns different data and different 46 | // formats. We want JSON, which from experimentation is returned for the `K*` and `P*` platforms (cf. 47 | // https://github.com/tweaselORG/parse-tunes/issues/1). 48 | // As per the investigation in https://github.com/tweaselORG/parse-tunes/issues/2#issuecomment-1377283817, only 49 | // platforms `25` and `30` return the iPad top charts. Those are `K8` and `K84`, respectively. Assuming that the 50 | // number represents the iOS version where the platform was first introduced, it makes sense to go with the newer, 51 | // i.e. `30`, which is `K84` and presumably iOS 8.4. 52 | // Accordingly, we use `29` (`P84`) for iPhone. 53 | const ipadCharts = Object.entries(charts).reduce((acc, [name, id]) => { 54 | if (name.endsWith('Ipad')) acc.push(id); 55 | return acc; 56 | }, []); 57 | const platform = ipadCharts.includes(request.chart) ? 30 : 29; 58 | 59 | const res = await fetch(topAppsApiUrl(request.genre, request.chart), { 60 | method: 'GET', 61 | headers: { 62 | // We are deliberately not setting a language, since we are only retrieving the app IDs. 63 | 'X-Apple-Store-Front': `${request.country},${platform}`, 64 | }, 65 | }).then((response) => response.json()); 66 | 67 | // Note: It's a bit silly but `$.pageData.segmentedControl.segments[0].pageData.topCharts` contains _all_ top charts 68 | // and we're just throwing away the other ones (see 69 | // https://github.com/tweaselORG/parse-tunes/issues/2#issuecomment-1377239436). But I haven't found a way to 70 | // make the request more specific. 71 | return res.pageData.segmentedControl.segments[0].pageData.selectedChart.adamIds; 72 | } 73 | -------------------------------------------------------------------------------- /src/endpoints/search.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'cross-fetch'; 2 | import type { UnionToIntersection } from 'type-fest'; 3 | import type { 4 | AppDetailsPlatformInRequest, 5 | AppDetailsPlatformInResponse, 6 | AppDetailsPlatformInResponseForRequest, 7 | AppDetailsResponseFragmentPerAttribute, 8 | } from '../common/app-meta'; 9 | import type { AllowedLanguagesPerCountryInMediaApi, MediaApiCountry } from '../common/consts'; 10 | 11 | /** Parameters for an app search request. */ 12 | export type AppSearchRequest = { 13 | /** The term to search for. */ 14 | searchTerm: string; 15 | 16 | /** 17 | * The platform(s) for which to fetch details about the found apps. Will fetch details for all platforms if this 18 | * parameter isn't specified. 19 | */ 20 | platforms?: Platforms; 21 | 22 | /** Which country's App Store to use. */ 23 | country: Country; 24 | /** The language in which to fetch the app details. */ 25 | language: AllowedLanguagesPerCountryInMediaApi[Country]; 26 | }; 27 | 28 | export const appSearchApiUrl = ( 29 | request: AppSearchRequest 30 | ) => 31 | // The `limit` parameter is hard-coded because other values result in 403 errors, see: https://github.com/tweaselORG/parse-tunes/issues/12#issuecomment-2122503518 32 | `https://tools.applemediaservices.com/api/apple-media/apps/${request.country}/search.json?types=apps&term=${ 33 | request.searchTerm 34 | }&l=${request.language}&limit=25&platform=${request.platforms?.[0] || 'web'}&additionalPlatforms=${ 35 | request.platforms ? request.platforms?.slice(1).join(',') : 'iphone,appletv,ipad,mac,watch' 36 | }`; 37 | 38 | /** 39 | * The attributes that are returned in the app search response. 40 | * 41 | * These are currently not configurable. 42 | */ 43 | export type AppSearchReturnedAttribute = 44 | | 'supportsArcade' 45 | | 'familyShareEnabledDate' 46 | | 'isFirstPartyHideableApp' 47 | | 'contentRatingsBySystem' 48 | | 'deviceFamilies' 49 | | 'chartPositions' 50 | | 'url' 51 | | 'usesLocationBackgroundMode' 52 | | 'userRating' 53 | | 'name' 54 | | 'genreDisplayName' 55 | | 'isPreorder' 56 | | 'isIOSBinaryMacOSCompatible' 57 | | 'artistName' 58 | | 'reviewsRestricted' 59 | | 'sellerLabel' 60 | | 'hasEula' 61 | | 'seller' 62 | | 'copyright' 63 | | 'minimumMacOSVersion' 64 | | 'isStandaloneWithCompanionForWatchOS' 65 | | 'isAppleWatchSupported' 66 | | 'is32bitOnly' 67 | | 'hasSafariExtension' 68 | | 'languageList' 69 | | 'requiresGameController' 70 | | 'requiredCapabilities' 71 | | 'offers' 72 | | 'supportedLocales' 73 | | 'requires32bit' 74 | | 'isSiriSupported' 75 | | 'isGameCenterEnabled' 76 | | 'releaseDate' 77 | | 'minimumOSVersion' 78 | | 'hasInAppPurchases' 79 | | 'bundleId' 80 | | 'hasMessagesExtension' 81 | | 'supportsGameController' 82 | | 'artwork' 83 | | 'hasFamilyShareableInAppPurchases' 84 | | 'isStandaloneForWatchOS' 85 | | 'isHiddenFromSpringboard' 86 | | 'isDeliveredInIOSAppForWatchOS' 87 | | 'hasPrivacyPolicyText' 88 | | 'editorialArtwork' 89 | | 'supportsPassbook' 90 | | 'requirementsString' 91 | | 'externalVersionId'; 92 | 93 | /** 94 | * The response from the app search API. 95 | * 96 | * Note: There is no publicly available documentation for the API responses. The types were extrapolated from a few 97 | * tested responses. They may not be 100 % accurate. 98 | */ 99 | export type AppSearchResponse = UnionToIntersection< 100 | AppDetailsResponseFragmentPerAttribute[AppSearchReturnedAttribute] 101 | >[]; 102 | 103 | /** 104 | * Search for apps on the the App Store. You can request a lot of different information about the app. The `attributes` 105 | * parameter specifies which attributes to fetch. See {@link appDetailsAvailableAttributes} for a list of all available 106 | * attributes. 107 | * 108 | * @param request The request parameters. 109 | * 110 | * @returns The app details, typed according to the attributes you specified. 111 | */ 112 | export async function searchApps( 113 | request: AppSearchRequest 114 | ): Promise> { 115 | const res = await fetch(appSearchApiUrl(request), { method: 'GET' }) 116 | .then((response) => response.text()) 117 | .then((r) => JSON.parse(r.trim())); 118 | 119 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 120 | return res.apps.data.map((a: any) => a.attributes); 121 | } 122 | -------------------------------------------------------------------------------- /src/endpoints/app-details.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'cross-fetch'; 2 | import type { UnionToIntersection } from 'type-fest'; 3 | import type { 4 | AppDetailsAvailableAttribute, 5 | AppDetailsPlatformInRequest, 6 | AppDetailsPlatformInResponse, 7 | AppDetailsPlatformInResponseForRequest, 8 | AppDetailsResponseFragmentPerAttribute, 9 | } from '../common/app-meta'; 10 | import type { AllowedLanguagesPerCountryInMediaApi, MediaApiCountry } from '../common/consts'; 11 | 12 | /** 13 | * List of URLs to pages on the App Store that contain a token for Apple's media API (amp-api.apps.apple.com) in their 14 | * response. 15 | * 16 | * @remarks 17 | * These are in the order of their response size. We'll try the smallest one first. 18 | */ 19 | export const appDetailsTokenUrls = [ 20 | 'https://apps.apple.com/404', 21 | 'https://apps.apple.com/story/id1538632801', 22 | 'https://apps.apple.com/us/app/facebook/id284882215', 23 | ] as const; 24 | 25 | /** 26 | * Fetch a token for Apple's media API (amp-api.apps.apple.com), to be used with the {@link fetchAppDetails} function. 27 | * The token can be used many times (until it expires). 28 | * 29 | * @remarks 30 | * The token is extracted from the HTML of an App Store page (see: https://github.com/tweaselORG/parse-tunes/issues/6). 31 | * 32 | * The token appears to be the same for everyone, and changes from time to time (around every four months). It is a JWT, 33 | * which you can parse to get the expiration date. 34 | * @returns The token. 35 | */ 36 | export async function fetchMediaApiToken(): Promise { 37 | let lastError: Error | undefined; 38 | 39 | for (const url of appDetailsTokenUrls) { 40 | try { 41 | const html = await fetch(url).then((r) => r.text()); 42 | // I know, I know. Thou shalt not parse HTML using regex. But the page seems to be pretty stable, and it 43 | // doesn't seem worth it to pull in an HTML parser just for this. *fingerscrossed* 44 | const metaContent = html.match(//); 45 | if (!metaContent?.[1]) continue; 46 | 47 | const config = JSON.parse(decodeURIComponent(metaContent[1])); 48 | if (config.MEDIA_API.token) return config.MEDIA_API.token; 49 | } catch (e) { 50 | if (e instanceof Error) lastError = e; 51 | } 52 | } 53 | 54 | throw new Error('Failed to fetch token for media API.', { cause: lastError }); 55 | } 56 | 57 | /** Parameters for an app details request. */ 58 | export type AppDetailsRequest< 59 | Country extends MediaApiCountry, 60 | Platforms extends AppDetailsPlatformInRequest[], 61 | Attributes extends AppDetailsAvailableAttribute[] 62 | > = { 63 | /** The numerical ID of the app for which to fetch the details. */ 64 | appId: number; 65 | /** 66 | * The platform(s) for which to fetch details about the requested app. Will fetch details for all platforms if this 67 | * parameter isn't specified. 68 | */ 69 | platforms?: Platforms; 70 | 71 | /** The attributes to fetch. See {@link appDetailsAvailableAttributes} for a list. */ 72 | attributes: Attributes; 73 | 74 | /** Which country's App Store to use. */ 75 | country: Country; 76 | /** The language in which to fetch the details. */ 77 | language: AllowedLanguagesPerCountryInMediaApi[Country]; 78 | 79 | /** 80 | * The token to use for authentication. 81 | * 82 | * If you don't provide one, it will be fetched automatically. However, if you want to fetch the details for 83 | * multiple apps, it's recommended to fetch the token once and then pass it to all the requests instead of 84 | * re-fetching the token for each request. You can use {@link fetchMediaApiToken} to fetch a token beforehand. 85 | */ 86 | token?: string; 87 | }; 88 | 89 | export const appDetailsApiUrl = < 90 | Country extends MediaApiCountry, 91 | Platforms extends AppDetailsPlatformInRequest[], 92 | Attributes extends AppDetailsAvailableAttribute[] 93 | >( 94 | request: AppDetailsRequest 95 | ) => 96 | `https://amp-api.apps.apple.com/v1/catalog/${request.country}/apps/${request.appId}?platform=${ 97 | request.platforms?.[0] || 'web' 98 | }&additionalPlatforms=${ 99 | request.platforms ? request.platforms?.slice(1).join(',') : 'iphone,appletv,ipad,mac,watch' 100 | }&l=${request.language}&fields=${request.attributes.join(',')}`; 101 | 102 | /** 103 | * The response from the app details API, typed according to the attributes specified in the request. 104 | * 105 | * Note: There is no publicly available documentation for the API responses. The types were extrapolated from a few 106 | * tested responses. They may not be 100 % accurate. 107 | */ 108 | export type AppDetailsResponse< 109 | Platforms extends AppDetailsPlatformInResponse, 110 | Attributes extends AppDetailsAvailableAttribute 111 | > = UnionToIntersection[Attributes]>; 112 | 113 | /** 114 | * Fetch the details for an app from the App Store. You can request a lot of different information about the app. The 115 | * `attributes` parameter specifies which attributes to fetch. See {@link appDetailsAvailableAttributes} for a list of 116 | * all available attributes. 117 | * 118 | * @param request The request parameters. 119 | * 120 | * @returns The app details, typed according to the attributes you specified. 121 | */ 122 | export async function fetchAppDetails< 123 | Country extends MediaApiCountry, 124 | Platforms extends AppDetailsPlatformInRequest[], 125 | Attributes extends AppDetailsAvailableAttribute[] 126 | >( 127 | request: AppDetailsRequest 128 | ): Promise> { 129 | const token = request.token || (await fetchMediaApiToken()); 130 | 131 | const res = await fetch(appDetailsApiUrl(request), { 132 | method: 'GET', 133 | headers: { 134 | Authorization: `Bearer ${token}`, 135 | Origin: 'https://apps.apple.com', 136 | }, 137 | }) 138 | .then((response) => response.text()) 139 | .then((r) => JSON.parse(r.trim())); 140 | 141 | return res.data[0].attributes; 142 | } 143 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | tmp/ 2 | *.tmp 3 | tmp.* 4 | *.tmp.* 5 | 6 | dist/ 7 | 8 | # Created by https://www.toptal.com/developers/gitignore/api/linux,macos,windows,visualstudiocode,jetbrains+all,sublimetext,node 9 | # Edit at https://www.toptal.com/developers/gitignore?templates=linux,macos,windows,visualstudiocode,jetbrains+all,sublimetext,node 10 | 11 | ### JetBrains+all ### 12 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 13 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 14 | 15 | # User-specific stuff 16 | .idea/**/workspace.xml 17 | .idea/**/tasks.xml 18 | .idea/**/usage.statistics.xml 19 | .idea/**/dictionaries 20 | .idea/**/shelf 21 | 22 | # Generated files 23 | .idea/**/contentModel.xml 24 | 25 | # Sensitive or high-churn files 26 | .idea/**/dataSources/ 27 | .idea/**/dataSources.ids 28 | .idea/**/dataSources.local.xml 29 | .idea/**/sqlDataSources.xml 30 | .idea/**/dynamic.xml 31 | .idea/**/uiDesigner.xml 32 | .idea/**/dbnavigator.xml 33 | 34 | # Gradle 35 | .idea/**/gradle.xml 36 | .idea/**/libraries 37 | 38 | # Gradle and Maven with auto-import 39 | # When using Gradle or Maven with auto-import, you should exclude module files, 40 | # since they will be recreated, and may cause churn. Uncomment if using 41 | # auto-import. 42 | # .idea/artifacts 43 | # .idea/compiler.xml 44 | # .idea/jarRepositories.xml 45 | # .idea/modules.xml 46 | # .idea/*.iml 47 | # .idea/modules 48 | # *.iml 49 | # *.ipr 50 | 51 | # CMake 52 | cmake-build-*/ 53 | 54 | # Mongo Explorer plugin 55 | .idea/**/mongoSettings.xml 56 | 57 | # File-based project format 58 | *.iws 59 | 60 | # IntelliJ 61 | out/ 62 | 63 | # mpeltonen/sbt-idea plugin 64 | .idea_modules/ 65 | 66 | # JIRA plugin 67 | atlassian-ide-plugin.xml 68 | 69 | # Cursive Clojure plugin 70 | .idea/replstate.xml 71 | 72 | # Crashlytics plugin (for Android Studio and IntelliJ) 73 | com_crashlytics_export_strings.xml 74 | crashlytics.properties 75 | crashlytics-build.properties 76 | fabric.properties 77 | 78 | # Editor-based Rest Client 79 | .idea/httpRequests 80 | 81 | # Android studio 3.1+ serialized cache file 82 | .idea/caches/build_file_checksums.ser 83 | 84 | ### JetBrains+all Patch ### 85 | # Ignores the whole .idea folder and all .iml files 86 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 87 | 88 | .idea/ 89 | 90 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 91 | 92 | *.iml 93 | modules.xml 94 | .idea/misc.xml 95 | *.ipr 96 | 97 | # Sonarlint plugin 98 | .idea/sonarlint 99 | 100 | ### Linux ### 101 | *~ 102 | 103 | # temporary files which can be created if a process still has a handle open of a deleted file 104 | .fuse_hidden* 105 | 106 | # KDE directory preferences 107 | .directory 108 | 109 | # Linux trash folder which might appear on any partition or disk 110 | .Trash-* 111 | 112 | # .nfs files are created when an open file is removed but is still being accessed 113 | .nfs* 114 | 115 | ### macOS ### 116 | # General 117 | .DS_Store 118 | .AppleDouble 119 | .LSOverride 120 | 121 | # Icon must end with two \r 122 | Icon 123 | 124 | 125 | # Thumbnails 126 | ._* 127 | 128 | # Files that might appear in the root of a volume 129 | .DocumentRevisions-V100 130 | .fseventsd 131 | .Spotlight-V100 132 | .TemporaryItems 133 | .Trashes 134 | .VolumeIcon.icns 135 | .com.apple.timemachine.donotpresent 136 | 137 | # Directories potentially created on remote AFP share 138 | .AppleDB 139 | .AppleDesktop 140 | Network Trash Folder 141 | Temporary Items 142 | .apdisk 143 | 144 | ### Node ### 145 | # Logs 146 | logs 147 | *.log 148 | npm-debug.log* 149 | yarn-debug.log* 150 | yarn-error.log* 151 | lerna-debug.log* 152 | 153 | # Diagnostic reports (https://nodejs.org/api/report.html) 154 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 155 | 156 | # Runtime data 157 | pids 158 | *.pid 159 | *.seed 160 | *.pid.lock 161 | 162 | # Directory for instrumented libs generated by jscoverage/JSCover 163 | lib-cov 164 | 165 | # Coverage directory used by tools like istanbul 166 | coverage 167 | *.lcov 168 | 169 | # nyc test coverage 170 | .nyc_output 171 | 172 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 173 | .grunt 174 | 175 | # Bower dependency directory (https://bower.io/) 176 | bower_components 177 | 178 | # node-waf configuration 179 | .lock-wscript 180 | 181 | # Compiled binary addons (https://nodejs.org/api/addons.html) 182 | build/Release 183 | 184 | # Dependency directories 185 | node_modules/ 186 | jspm_packages/ 187 | 188 | # TypeScript v1 declaration files 189 | typings/ 190 | 191 | # TypeScript cache 192 | *.tsbuildinfo 193 | 194 | # Optional npm cache directory 195 | .npm 196 | 197 | # Optional eslint cache 198 | .eslintcache 199 | 200 | # Microbundle cache 201 | .rpt2_cache/ 202 | .rts2_cache_cjs/ 203 | .rts2_cache_es/ 204 | .rts2_cache_umd/ 205 | 206 | # Optional REPL history 207 | .node_repl_history 208 | 209 | # Output of 'npm pack' 210 | *.tgz 211 | 212 | # Yarn Integrity file 213 | .yarn-integrity 214 | 215 | # dotenv environment variables file 216 | .env 217 | .env.test 218 | .env*.local 219 | 220 | # parcel-bundler cache (https://parceljs.org/) 221 | .cache 222 | .parcel-cache 223 | 224 | # Next.js build output 225 | .next 226 | 227 | # Nuxt.js build / generate output 228 | .nuxt 229 | dist 230 | 231 | # Gatsby files 232 | .cache/ 233 | # Comment in the public line in if your project uses Gatsby and not Next.js 234 | # https://nextjs.org/blog/next-9-1#public-directory-support 235 | # public 236 | 237 | # vuepress build output 238 | .vuepress/dist 239 | 240 | # Serverless directories 241 | .serverless/ 242 | 243 | # FuseBox cache 244 | .fusebox/ 245 | 246 | # DynamoDB Local files 247 | .dynamodb/ 248 | 249 | # TernJS port file 250 | .tern-port 251 | 252 | # Stores VSCode versions used for testing VSCode extensions 253 | .vscode-test 254 | 255 | ### SublimeText ### 256 | # Cache files for Sublime Text 257 | *.tmlanguage.cache 258 | *.tmPreferences.cache 259 | *.stTheme.cache 260 | 261 | # Workspace files are user-specific 262 | *.sublime-workspace 263 | 264 | # Project files should be checked into the repository, unless a significant 265 | # proportion of contributors will probably not be using Sublime Text 266 | # *.sublime-project 267 | 268 | # SFTP configuration file 269 | sftp-config.json 270 | 271 | # Package control specific files 272 | Package Control.last-run 273 | Package Control.ca-list 274 | Package Control.ca-bundle 275 | Package Control.system-ca-bundle 276 | Package Control.cache/ 277 | Package Control.ca-certs/ 278 | Package Control.merged-ca-bundle 279 | Package Control.user-ca-bundle 280 | oscrypto-ca-bundle.crt 281 | bh_unicode_properties.cache 282 | 283 | # Sublime-github package stores a github token in this file 284 | # https://packagecontrol.io/packages/sublime-github 285 | GitHub.sublime-settings 286 | 287 | ### VisualStudioCode ### 288 | .vscode/* 289 | !.vscode/tasks.json 290 | !.vscode/launch.json 291 | *.code-workspace 292 | 293 | ### VisualStudioCode Patch ### 294 | # Ignore all local history of files 295 | .history 296 | .ionide 297 | 298 | ### Windows ### 299 | # Windows thumbnail cache files 300 | Thumbs.db 301 | Thumbs.db:encryptable 302 | ehthumbs.db 303 | ehthumbs_vista.db 304 | 305 | # Dump file 306 | *.stackdump 307 | 308 | # Folder config file 309 | [Dd]esktop.ini 310 | 311 | # Recycle Bin used on file shares 312 | $RECYCLE.BIN/ 313 | 314 | # Windows Installer files 315 | *.cab 316 | *.msi 317 | *.msix 318 | *.msm 319 | *.msp 320 | 321 | # Windows shortcuts 322 | *.lnk 323 | 324 | # End of 325 | # https://www.toptal.com/developers/gitignore/api/linux,macos,windows,visualstudiocode,jetbrains+all,sublimetext,node 326 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # parse-tunes 2 | 3 | > Library for fetching select data on iOS apps from the Apple Apple Store via undocumented internal iTunes APIs. 4 | 5 | This library is able to fetch and parse data from undocumented internal API endpoints of the Apple App Store. Currently, it has the following features: 6 | 7 | * Fetch the **charts of the most popular apps**, including filtering by genre and chart. 8 | * **Fetch details** (including **privacy labels**) for individual apps. 9 | * **Search** for apps. 10 | 11 | We'll extend the supported API endpoints in the future. The focus will mostly be on functions useful for research into mobile privacy and data protection. 12 | 13 | As all the used endpoints are undocumented, we had to resort to reverse-engineering them. It is possible that we have misinterpreted the meaning of parameters or endpoints. It is also entirely possible that some or all of the endpoints will stop working out of the blue at some point, or change their request and/or response formats. 14 | 15 | ## Installation 16 | 17 | You can install parse-tunes using yarn or npm: 18 | 19 | ```sh 20 | yarn add parse-tunes 21 | # or `npm i parse-tunes` 22 | ``` 23 | 24 | ## API reference 25 | 26 | A full API reference can be found in the [`docs` folder](/docs/README.md). 27 | 28 | ## Example usage 29 | 30 | ### Fetch app top charts 31 | 32 | The following example fetches the app IDs of the current 200 top free iPhone apps across all categories for Germany: 33 | 34 | ```ts 35 | import { fetchTopApps, charts, countries, genres } from 'parse-tunes'; 36 | 37 | (async () => { 38 | const topChart = await fetchTopApps({ genre: genres.all, chart: charts.topFreeIphone, country: countries.DE }); 39 | console.log(topChart.length); // 200 40 | console.log(topChart[0]); // 1186271926 41 | })(); 42 | ``` 43 | 44 | Fetching more app metadata in addition to the app IDs is currently not possible due to server-side limitations by the endpoint we're using. See [#2](https://github.com/tweaselORG/parse-tunes/issues/2) for details. 45 | 46 | ### Fetch app metadata 47 | 48 | The following example fetches the developer name and custom artwork for the Facebook app on iPhone for the German App Store in German: 49 | 50 | ```ts 51 | import { fetchAppDetails } from 'parse-tunes'; 52 | 53 | (async () => { 54 | const appDetails = await fetchAppDetails({ 55 | appId: 284882215, 56 | platforms: ['iphone'], 57 | attributes: ['artistName', 'customArtwork'], 58 | country: 'DE', 59 | language: 'de-DE', 60 | }); 61 | console.log(appDetails.artistName); 62 | // Meta Platforms, Inc. 63 | console.log(appDetails.platformAttributes.ios?.customAttributes.default.default.customArtwork.url); 64 | // https://is5-ssl.mzstatic.com/image/thumb/Purple113/v4/45/ab/be/45abbeac-3a7e-aa86-c1c5-007c09df6d7c/Icon-Production-0-1x_U007emarketing-0-7-0-85-220.png/{w}x{h}{c}.{f} 65 | })(); 66 | ``` 67 | 68 | This function uses Apple's internal media API (amp-api.apps.apple.com), which requires a token. If you don't provide a token, one will be fetched automatically. If you want to fetch data for multiple apps, it is recommended to fetch the token once using `fetchMediaApiToken()` and pass it to all subsequent calls to `fetchAppDetails()` to avoid the unnecessary requests: 69 | 70 | ```ts 71 | import { fetchAppDetails, fetchMediaApiToken } from 'parse-tunes'; 72 | 73 | (async () => { 74 | const token = await fetchMediaApiToken(); 75 | 76 | for (const appId of [1444383602, 490109661, 462054704]) { 77 | const appDetails = await fetchAppDetails({ 78 | appId, 79 | platforms: ['ipad', 'watch'], 80 | attributes: ['bundleId', 'isIOSBinaryMacOSCompatible'], 81 | country: 'US', 82 | language: 'en-US', 83 | token, 84 | }); 85 | console.log(appDetails.platformAttributes.ios?.bundleId, '::', appDetails.isIOSBinaryMacOSCompatible); 86 | } 87 | })(); 88 | ``` 89 | 90 | Through the app details function, you can also fetch an app's privacy labels: 91 | 92 | ```ts 93 | import { fetchAppDetails } from 'parse-tunes'; 94 | 95 | (async () => { 96 | const { privacyDetails } = await fetchAppDetails({ 97 | appId: 1113153706, 98 | platforms: ['iphone'], 99 | attributes: ['privacyDetails'], 100 | country: 'DE', 101 | language: 'en-GB', 102 | }); 103 | 104 | console.dir(privacyDetails, { depth: null }); 105 | })(); 106 | ``` 107 | 108 |
109 | Privacy label response 110 | The response looks like this: 111 | 112 | ```ts 113 | { 114 | managePrivacyChoicesUrl: null, 115 | privacyTypes: [ 116 | { 117 | privacyType: 'Data Linked to You', 118 | identifier: 'DATA_LINKED_TO_YOU', 119 | description: 'The following data, which may be collected and linked to your identity, may be used for the following purposes:', 120 | dataCategories: [], 121 | purposes: [ 122 | { 123 | purpose: 'Analytics', 124 | identifier: 'ANALYTICS', 125 | dataCategories: [ 126 | { 127 | dataCategory: 'Location', 128 | identifier: 'LOCATION', 129 | dataTypes: [ 'Coarse Location' ] 130 | }, 131 | { 132 | dataCategory: 'Identifiers', 133 | identifier: 'IDENTIFIERS', 134 | dataTypes: [ 'User ID', 'Device ID' ] 135 | }, 136 | { 137 | dataCategory: 'Usage Data', 138 | identifier: 'USAGE_DATA', 139 | dataTypes: [ 'Product Interaction' ] 140 | }, 141 | { 142 | dataCategory: 'Diagnostics', 143 | identifier: 'DIAGNOSTICS', 144 | dataTypes: [ 'Performance Data' ] 145 | } 146 | ] 147 | }, 148 | { 149 | purpose: 'App Functionality', 150 | identifier: 'APP_FUNCTIONALITY', 151 | dataCategories: [ 152 | { 153 | dataCategory: 'Location', 154 | identifier: 'LOCATION', 155 | dataTypes: [ 'Precise Location', 'Coarse Location' ] 156 | }, 157 | { 158 | dataCategory: 'Contact Info', 159 | identifier: 'CONTACT_INFO', 160 | dataTypes: [ 'Email Address', 'Name', 'Phone Number' ] 161 | }, 162 | { 163 | dataCategory: 'Contacts', 164 | identifier: 'CONTACTS', 165 | dataTypes: [ 'Contacts' ] 166 | }, 167 | { 168 | dataCategory: 'User Content', 169 | identifier: 'USER_CONTENT', 170 | dataTypes: [ 171 | 'Photos or Videos', 172 | 'Audio Data', 173 | 'Other User Content' 174 | ] 175 | }, 176 | { 177 | dataCategory: 'Identifiers', 178 | identifier: 'IDENTIFIERS', 179 | dataTypes: [ 'User ID', 'Device ID' ] 180 | }, 181 | { 182 | dataCategory: 'Usage Data', 183 | identifier: 'USAGE_DATA', 184 | dataTypes: [ 'Product Interaction' ] 185 | }, 186 | { 187 | dataCategory: 'Diagnostics', 188 | identifier: 'DIAGNOSTICS', 189 | dataTypes: [ 190 | 'Crash Data', 191 | 'Performance Data', 192 | 'Other Diagnostic Data' 193 | ] 194 | } 195 | ] 196 | } 197 | ] 198 | } 199 | ] 200 | } 201 | ``` 202 | 203 |
204 | 205 | ### Search for apps 206 | 207 | The following example searches the German App Store for apps with the term "education" and lists their names: 208 | 209 | ```ts 210 | import { fetchAppDetails } from 'parse-tunes'; 211 | 212 | (async () => { 213 | const apps = await searchApps({ searchTerm: 'education', country: 'DE', language: 'en-GB' }); 214 | 215 | for (const app of apps) console.log(app.name); 216 | // Microsoft OneNote 217 | // Goodnotes 6 218 | // StudyCards - Karteikarten 219 | // … 220 | })(); 221 | ``` 222 | 223 | The metadata in the search results has the same format as for the app details, but here, you cannot choose which fields you want to fetch. 224 | 225 | ## License 226 | 227 | This code is licensed under the MIT license, see the [`LICENSE`](LICENSE) file for details. 228 | 229 | Issues and pull requests are welcome! Please be aware that by contributing, you agree for your work to be licensed under an MIT license. 230 | -------------------------------------------------------------------------------- /src/common/app-meta.ts: -------------------------------------------------------------------------------- 1 | import type { GenreName } from './consts'; 2 | 3 | /** 4 | * The attributes (fields) that can be requested from the app details endpoint. 5 | * 6 | * No publicly available documentation exists for these. In most cases, it is quite obvious what they mean from the name 7 | * and/or returned data. 8 | * 9 | * @remarks 10 | * Compiled through trial and error and from looking at requests made by the App Store app. 11 | * 12 | * @see {@link https://github.com/tweaselORG/parse-tunes/issues/6} 13 | */ 14 | export const appDetailsAvailableAttributes = [ 15 | 'artistName', 16 | 'artwork', 17 | 'bundleId', 18 | 'chartPositions', 19 | 'contentRatingsBySystem', 20 | 'copyright', 21 | 'customArtwork', 22 | 'customScreenshotsByType', 23 | 'customVideoPreviewsByType', 24 | 'description', 25 | 'deviceFamilies', 26 | 'editorialArtwork', 27 | 'eula', 28 | 'externalVersionId', 29 | 'familyShareEnabledDate', 30 | 'fileSizeByDevice', 31 | 'genreDisplayName', 32 | 'hasEula', 33 | 'hasFamilyShareableInAppPurchases', 34 | 'hasInAppPurchases', 35 | 'hasMessagesExtension', 36 | 'hasPrivacyPolicyText', 37 | 'hasSafariExtension', 38 | 'is32bitOnly', 39 | 'isAppleWatchSupported', 40 | 'isDeliveredInIOSAppForWatchOS', 41 | 'isFirstPartyHideableApp', 42 | 'isGameCenterEnabled', 43 | 'isHiddenFromSpringboard', 44 | 'isIOSBinaryMacOSCompatible', 45 | 'isPreorder', 46 | 'isSiriSupported', 47 | 'isStandaloneForWatchOS', 48 | 'isStandaloneWithCompanionForWatchOS', 49 | 'languageList', 50 | 'maxPlayers', 51 | 'messagesScreenshots', 52 | 'minimumMacOSVersion', 53 | 'minimumOSVersion', 54 | 'minPlayers', 55 | 'name', 56 | 'offers', 57 | 'privacy', 58 | 'privacyDetails', 59 | 'privacyPolicyText', 60 | 'privacyPolicyUrl', 61 | 'releaseDate', 62 | 'remoteControllerRequirement', 63 | 'requiredCapabilities', 64 | 'requirementsByDeviceFamily', 65 | 'requirementsString', 66 | 'requires32bit', 67 | 'requiresGameController', 68 | 'reviewsRestricted', 69 | 'seller', 70 | 'sellerLabel', 71 | 'supportedLocales', 72 | 'supportsArcade', 73 | 'supportsFunCamera', 74 | 'supportsGameController', 75 | 'supportsPassbook', 76 | 'supportURLForLanguage', 77 | 'url', 78 | 'userRating', 79 | 'usesLocationBackgroundMode', 80 | 'versionHistory', 81 | 'websiteUrl', 82 | ] as const; 83 | /** An attribute (field) that can be requested from the app details endpoint. */ 84 | export type AppDetailsAvailableAttribute = (typeof appDetailsAvailableAttributes)[number]; 85 | 86 | // Annoyingly, the API uses different platform names in the request and in the response, see 87 | // https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1400240548. 88 | /** 89 | * A platform that can appear in the `platform` or `additionalPlatforms` parameter of a request to the app details or 90 | * search endpoint. 91 | */ 92 | export type AppDetailsPlatformInRequest = 'web' | 'iphone' | 'appletv' | 'ipad' | 'mac' | 'watch'; 93 | /** 94 | * A type mapping from the platforms that can appear in a request to the app details or search endpoint to the key of 95 | * the `platformAttributes` object in the response that they cause to be included. 96 | * 97 | * @see {@link https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1400240548} 98 | */ 99 | export type AppDetailsPlatformInResponseForRequest = { 100 | iphone: 'ios'; 101 | ipad: 'ios'; 102 | watch: 'ios'; 103 | appletv: 'appletvos'; 104 | mac: 'osx'; 105 | web: undefined; 106 | }; 107 | /** 108 | * A platform that can appear in the response from the app details or search endpoint as a key of the 109 | * `platformAttributes` object. 110 | * 111 | * @see {@link https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1400240548} 112 | */ 113 | export type AppDetailsPlatformInResponse = 114 | AppDetailsPlatformInResponseForRequest[keyof AppDetailsPlatformInResponseForRequest]; 115 | 116 | /** Small helper for response fragments that are listed under `platformAttributes`. */ 117 | export type PlatformAttributes = { 118 | platformAttributes: { 119 | [key in Exclude]?: ResponseFragment; 120 | }; 121 | }; 122 | /** An artwork image in a response fragment. */ 123 | export type AppDetailsArtwork = { 124 | width: number; 125 | height: number; 126 | url: string; 127 | bgColor: string; 128 | textColor1: string; 129 | textColor2: string; 130 | textColor3: string; 131 | textColor4: string; 132 | }; 133 | /** A list of privacy types as declared in a privacy label, in short format as returned for the `privacy` attribute. */ 134 | export type PrivacyTypesShort = { 135 | privacyType: string; 136 | identifier: 'DATA_NOT_COLLECTED' | 'DATA_USED_TO_TRACK_YOU' | 'DATA_LINKED_TO_YOU' | 'DATA_NOT_LINKED_TO_YOU'; 137 | description: string; 138 | dataCategories: { 139 | dataCategory: string; 140 | identifier: string; 141 | }[]; 142 | }[]; 143 | /** 144 | * A list of privacy types as declared in a privacy label, in long format as returned for the `privacyDetails` 145 | * attribute. 146 | */ 147 | export type PrivacyTypes = { 148 | privacyType: string; 149 | identifier: 'DATA_NOT_COLLECTED' | 'DATA_USED_TO_TRACK_YOU' | 'DATA_LINKED_TO_YOU' | 'DATA_NOT_LINKED_TO_YOU'; 150 | description: string; 151 | dataCategories: { 152 | dataCategory: string; 153 | identifier: string; 154 | dataTypes: string[]; 155 | }[]; 156 | purposes: { 157 | purpose: string; 158 | identifier: string; 159 | dataCategories: { 160 | dataCategory: string; 161 | identifier: string; 162 | dataTypes: string[]; 163 | }[]; 164 | }[]; 165 | }[]; 166 | /** Type mapping from the possible attributes to the additional data they add in the response. */ 167 | export type AppDetailsResponseFragmentPerAttribute = { 168 | artistName: { artistName: string }; 169 | artwork: PlatformAttributes; 170 | bundleId: PlatformAttributes; 171 | chartPositions: { 172 | chartPositions?: { 173 | [store in 'appStore' | 'messages']?: { 174 | position: string; 175 | genreName: string; 176 | genre: number; 177 | chart: string; 178 | chartLink: string; 179 | }; 180 | }; 181 | }; 182 | contentRatingsBySystem: { 183 | contentRatingsBySystem: { appsApple: { name: string; value: number; rank: number; advisories?: string[] } }; 184 | }; 185 | copyright: PlatformAttributes; 186 | customArtwork: PlatformAttributes< 187 | Platforms, 188 | { customAttributes: { default: { default: { customArtwork: AppDetailsArtwork } } } } 189 | >; 190 | customScreenshotsByType: PlatformAttributes< 191 | Platforms, 192 | { 193 | customAttributes: { 194 | default: { default: { customScreenshotsByType: { [device: string]: AppDetailsArtwork[] } } }; 195 | }; 196 | } 197 | >; 198 | customVideoPreviewsByType: PlatformAttributes< 199 | Platforms, 200 | { 201 | customAttributes: { 202 | default: { 203 | default: { 204 | customVideoPreviewsByType: { 205 | [device: string]: { previewFrame: AppDetailsArtwork; video: string }[]; 206 | }; 207 | }; 208 | }; 209 | }; 210 | } 211 | >; 212 | description: PlatformAttributes; 213 | deviceFamilies: { deviceFamilies: string[] }; 214 | editorialArtwork: PlatformAttributes }>; 215 | eula: { eula: string }; 216 | externalVersionId: PlatformAttributes; 217 | familyShareEnabledDate: { familyShareEnabledDate: string }; 218 | fileSizeByDevice: { fileSizeByDevice: { [device: string]: number } }; 219 | genreDisplayName: { genreDisplayName: GenreName }; 220 | hasEula: { hasEula: boolean }; 221 | hasFamilyShareableInAppPurchases: PlatformAttributes; 222 | hasInAppPurchases: PlatformAttributes; 223 | hasMessagesExtension: PlatformAttributes; 224 | hasPrivacyPolicyText: PlatformAttributes; 225 | hasSafariExtension: PlatformAttributes; 226 | is32bitOnly: PlatformAttributes; 227 | isAppleWatchSupported: PlatformAttributes; 228 | isDeliveredInIOSAppForWatchOS: PlatformAttributes; 229 | isFirstPartyHideableApp: { isFirstPartyHideableApp: boolean }; 230 | isGameCenterEnabled: PlatformAttributes; 231 | isHiddenFromSpringboard: PlatformAttributes; 232 | isIOSBinaryMacOSCompatible: { isIOSBinaryMacOSCompatible: boolean }; 233 | isPreorder: { isPreorder: boolean }; 234 | isSiriSupported: PlatformAttributes; 235 | isStandaloneForWatchOS: PlatformAttributes; 236 | isStandaloneWithCompanionForWatchOS: PlatformAttributes< 237 | Platforms, 238 | { isStandaloneWithCompanionForWatchOS: boolean } 239 | >; 240 | languageList: PlatformAttributes; 241 | maxPlayers: PlatformAttributes; 242 | messagesScreenshots: PlatformAttributes< 243 | Platforms, 244 | { messagesScreenshots?: { [device: string]: AppDetailsArtwork } } 245 | >; 246 | minimumMacOSVersion: PlatformAttributes; 247 | minimumOSVersion: PlatformAttributes; 248 | minPlayers: PlatformAttributes; 249 | name: { name: string }; 250 | offers: PlatformAttributes< 251 | Platforms, 252 | { 253 | offers: { 254 | buyParams: string; 255 | type: string; 256 | priceFormatted: string; 257 | price: number; 258 | currencyCode: string; 259 | assets: { flavor: string; size: number }[]; 260 | }[]; 261 | } 262 | >; 263 | privacy: { privacy: { privacyTypes: PrivacyTypesShort } }; 264 | privacyDetails: { privacyDetails: { managePrivacyChoicesUrl: string | null; privacyTypes: PrivacyTypes } }; 265 | privacyPolicyText: PlatformAttributes; 266 | privacyPolicyUrl: PlatformAttributes; 267 | releaseDate: PlatformAttributes; 268 | remoteControllerRequirement: PlatformAttributes; 269 | requiredCapabilities: PlatformAttributes; 270 | requirementsByDeviceFamily: { 271 | requirementsByDeviceFamily: { [device: string]: { deviceFamily: string; requirementsString: string } }; 272 | }; 273 | requirementsString: PlatformAttributes; 274 | requires32bit: PlatformAttributes; 275 | requiresGameController: PlatformAttributes; 276 | reviewsRestricted: { reviewsRestricted: boolean }; 277 | seller: PlatformAttributes; 278 | sellerLabel: { sellerLabel: string }; 279 | supportedLocales: PlatformAttributes; 280 | supportsArcade: { supportsArcade: boolean }; 281 | supportsFunCamera: PlatformAttributes; 282 | supportsGameController: PlatformAttributes; 283 | supportsPassbook: PlatformAttributes; 284 | supportURLForLanguage: PlatformAttributes; 285 | url: { url: string }; 286 | userRating: { 287 | userRating: { 288 | value: number; 289 | ratingCount: number; 290 | ratingCountList: [number, number, number, number, number]; 291 | ariaLabelForRating: string; 292 | }; 293 | }; 294 | usesLocationBackgroundMode: { usesLocationBackgroundMode: boolean }; 295 | versionHistory: PlatformAttributes< 296 | Platforms, 297 | { 298 | versionHistory: { 299 | versionDisplay: string; 300 | releaseNotes: string; 301 | releaseDate: string; 302 | releaseTimestamp: string; 303 | }[]; 304 | } 305 | >; 306 | websiteUrl: PlatformAttributes; 307 | }; 308 | -------------------------------------------------------------------------------- /src/common/consts.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The countries that can appear as the first parameter for the `X-Apple-Store-Front` header in a request to an iTunes 3 | * endpoint. 4 | * 5 | * @remarks 6 | * Generated from: 7 | * https://web.archive.org/web/20191206001952/https://affiliate.itunes.apple.com/resources/documentation/linking-to-the-itunes-music-store/#appendix 8 | * (using [this script](https://github.com/tweaselORG/parse-tunes/issues/1#issuecomment-1377105173)). 9 | */ 10 | export const countries = { 11 | DZ: 143563, 12 | AO: 143564, 13 | AI: 143538, 14 | AG: 143540, 15 | AR: 143505, 16 | AM: 143524, 17 | AU: 143460, 18 | AT: 143445, 19 | AZ: 143568, 20 | BH: 143559, 21 | BD: 143490, 22 | BB: 143541, 23 | BY: 143565, 24 | BE: 143446, 25 | BZ: 143555, 26 | BM: 143542, 27 | BO: 143556, 28 | BW: 143525, 29 | BR: 143503, 30 | VG: 143543, 31 | BN: 143560, 32 | BG: 143526, 33 | CA: 143455, 34 | KY: 143544, 35 | CL: 143483, 36 | CN: 143465, 37 | CO: 143501, 38 | CR: 143495, 39 | CI: 143527, 40 | HR: 143494, 41 | CY: 143557, 42 | CZ: 143489, 43 | DK: 143458, 44 | DM: 143545, 45 | DO: 143508, 46 | EC: 143509, 47 | EG: 143516, 48 | SV: 143506, 49 | EE: 143518, 50 | FI: 143447, 51 | FR: 143442, 52 | DE: 143443, 53 | GH: 143573, 54 | GR: 143448, 55 | GD: 143546, 56 | GT: 143504, 57 | GY: 143553, 58 | HN: 143510, 59 | HK: 143463, 60 | HU: 143482, 61 | IS: 143558, 62 | IN: 143467, 63 | ID: 143476, 64 | IE: 143449, 65 | IL: 143491, 66 | IT: 143450, 67 | JM: 143511, 68 | JP: 143462, 69 | JO: 143528, 70 | KZ: 143517, 71 | KE: 143529, 72 | KR: 143466, 73 | KW: 143493, 74 | LV: 143519, 75 | LB: 143497, 76 | LI: 143522, 77 | LT: 143520, 78 | LU: 143451, 79 | MO: 143515, 80 | MK: 143530, 81 | MG: 143531, 82 | MY: 143473, 83 | MV: 143488, 84 | ML: 143532, 85 | MT: 143521, 86 | MU: 143533, 87 | MX: 143468, 88 | MD: 143523, 89 | MS: 143547, 90 | NP: 143484, 91 | NL: 143452, 92 | NZ: 143461, 93 | NI: 143512, 94 | NE: 143534, 95 | NG: 143561, 96 | NO: 143457, 97 | OM: 143562, 98 | PK: 143477, 99 | PA: 143485, 100 | PY: 143513, 101 | PE: 143507, 102 | PH: 143474, 103 | PL: 143478, 104 | PT: 143453, 105 | QA: 143498, 106 | RO: 143487, 107 | RU: 143469, 108 | SA: 143479, 109 | SN: 143535, 110 | RS: 143500, 111 | SG: 143464, 112 | SK: 143496, 113 | SI: 143499, 114 | ZA: 143472, 115 | ES: 143454, 116 | LK: 143486, 117 | KN: 143548, 118 | LC: 143549, 119 | VC: 143550, 120 | SR: 143554, 121 | SE: 143456, 122 | CH: 143459, 123 | TW: 143470, 124 | TZ: 143572, 125 | TH: 143475, 126 | BS: 143539, 127 | TT: 143551, 128 | TN: 143536, 129 | TR: 143480, 130 | TC: 143552, 131 | UG: 143537, 132 | GB: 143444, 133 | UA: 143492, 134 | AE: 143481, 135 | UY: 143514, 136 | US: 143441, 137 | UZ: 143566, 138 | VE: 143502, 139 | VN: 143471, 140 | YE: 143571, 141 | } as const; 142 | /** 143 | * The ID of a country that can appear as the first parameter for the `X-Apple-Store-Front` header in a request to an 144 | * iTunes endpoint. 145 | */ 146 | export type StorefrontCountry = (typeof countries)[keyof typeof countries]; 147 | /** 148 | * The ISO 3166-1 alpha-2 code of a country that can appear as the first parameter for the `X-Apple-Store-Front` header 149 | * in a request to an iTunes endpoint. 150 | */ 151 | export type StorefrontCountryCode = keyof typeof countries; 152 | 153 | /** 154 | * The languages language that can appear as the second parameter for the `X-Apple-Store-Front` header in a request to 155 | * an iTunes endpoint. 156 | * 157 | * Note: Not all combinations between country and language are possible. A list of possible combinations can be obtained 158 | * from this Apple Music endpoint: https://api.music.apple.com/v1/storefronts. If no language is included in the header, 159 | * a sensible default is used (also listed in the API response). 160 | * 161 | * @remarks 162 | * Adapted after: https://stackoverflow.com/a/58776183/3211062. 163 | * 164 | * @todo Is this list complete? Can we find a better source? 165 | * ([#1](https://github.com/tweaselORG/parse-tunes/issues/1#issuecomment-1384047420)) 166 | */ 167 | export const languages = { 168 | 'en-US': 1, 169 | 'en-GB': 2, 170 | 'fr-FR': 3, 171 | 'de-DE': 4, 172 | 'fr-CA': 5, 173 | 'en-CA': 6, 174 | 'it-IT': 7, 175 | 'es-ES': 8, 176 | 'ja-JP': 9, 177 | 'nl-NL': 10, 178 | 'da-DK': 11, 179 | 'fi-FI': 12, 180 | 'ko-KR': 13, 181 | 'no-NO': 14, 182 | 'pt-BR': 15, 183 | 'ru-RU': 16, 184 | 'sv-SE': 17, 185 | 'zh-TW': 18, 186 | 'zh-CN': 19, 187 | 'pl-PL': 20, 188 | 'hu-HU': 21, 189 | 'cs-CZ': 22, 190 | 'el-GR': 23, 191 | 'pt-PT': 24, 192 | 'tr-TR': 25, 193 | 'en-AU': 27, 194 | 'es-MX': 28, 195 | 'uk-UA': 29, 196 | 'th-TH': 35, 197 | 'id-ID': 37, 198 | 'ms-MY': 38, 199 | 'ro-RO': 39, 200 | 'sk-SK': 40, 201 | 'hr-HR': 41, 202 | 'ca-ES': 42, 203 | 'vi-VI': 43, 204 | 'zh-HK': 45, 205 | 'hi-IN': 50, 206 | 'de-CH': 57, 207 | } as const; 208 | /** 209 | * The ID of a language that can appear as the second parameter for the `X-Apple-Store-Front` header in a request to an 210 | * iTunes endpoint. 211 | */ 212 | export type StorefrontLanguage = (typeof languages)[keyof typeof languages]; 213 | /** 214 | * The ISO 639-1 code of a language that can appear as the second parameter for the `X-Apple-Store-Front` header in a 215 | * request to an iTunes endpoint. 216 | */ 217 | export type StorefrontLanguageCode = keyof typeof languages; 218 | 219 | /** 220 | * The platforms that can appear as the third parameter for the `X-Apple-Store-Front` header in a request to an iTunes 221 | * endpoint. The list is not complete. 222 | * 223 | * From experimentation, `K8`, `P8`, `P84`, and `K84` always have a JSON response with the desired data. The others 224 | * return UI markup as HTML or XML (PLIST), some don't even include the desired data in the response. 225 | * 226 | * @remarks 227 | * Adapted after: https://gist.github.com/sgmurphy/1878352?permalink_comment_id=2977743#gistcomment-2977743. 228 | * 229 | * @todo Is this list complete? Can we find a better source? 230 | * ([#1](https://github.com/tweaselORG/parse-tunes/issues/1#issuecomment-1384068713)) 231 | */ 232 | export const platforms = { 233 | VolumeStore: 11, 234 | iTunes10: 12, 235 | EnterpriseStore: 14, 236 | K6: 15, 237 | P6: 16, 238 | iTunes11: 17, 239 | K7: 20, 240 | P7: 21, 241 | K71: 23, 242 | P71: 24, 243 | K8: 25, 244 | P8: 26, 245 | iTunes12: 28, 246 | P84: 29, 247 | K84: 30, 248 | iTunes122: 32, 249 | Configurator: 34, 250 | MacPodcasts1: 38, 251 | MacMusic1: 39, 252 | MacAMPLibrary1: 40, 253 | MacTV1: 41, 254 | Mac1: 42, 255 | } as const; 256 | /** 257 | * The ID of a platform that can appear as the third parameter for the `X-Apple-Store-Front` header in a request to an 258 | * iTunes endpoint. The list is not complete. 259 | */ 260 | export type StorefrontPlatform = (typeof platforms)[keyof typeof platforms]; 261 | /** 262 | * The internal name of a platform that can appear as the third parameter for the `X-Apple-Store-Front` header in a 263 | * request to an iTunes endpoint. The list is not complete. 264 | */ 265 | export type StorefrontPlatformName = keyof typeof platforms; 266 | 267 | /** 268 | * The genres and subgenres of apps on the App Store. 269 | * 270 | * @remarks 271 | * Generated from https://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres (using [this 272 | * script](https://github.com/tweaselORG/parse-tunes/issues/3#issuecomment-1384373531)). 273 | */ 274 | export const genres = { 275 | all: 36, 276 | Business: 6000, 277 | Weather: 6001, 278 | Utilities: 6002, 279 | Travel: 6003, 280 | Sports: 6004, 281 | 'Social Networking': 6005, 282 | Reference: 6006, 283 | Productivity: 6007, 284 | 'Photo & Video': 6008, 285 | News: 6009, 286 | Navigation: 6010, 287 | Music: 6011, 288 | Lifestyle: 6012, 289 | 'Health & Fitness': 6013, 290 | Games: 6014, 291 | Finance: 6015, 292 | Entertainment: 6016, 293 | Education: 6017, 294 | Books: 6018, 295 | Medical: 6020, 296 | 'Magazines & Newspapers': 6021, 297 | Catalogs: 6022, 298 | 'Food & Drink': 6023, 299 | Shopping: 6024, 300 | Stickers: 6025, 301 | 'Developer Tools': 6026, 302 | 'Graphics & Design': 6027, 303 | } as const; 304 | /** The ID of a genre or subgenre on the App Store. */ 305 | export type Genre = (typeof genres)[keyof typeof genres]; 306 | /** The name of a genre or subgenre on the App Store. */ 307 | export type GenreName = keyof typeof genres; 308 | 309 | /** 310 | * A mapping from the ISO 3166-1 alpha-2 code of countries to the language codes that they support in Apple's media API 311 | * (amp-api.apps.apple.com). 312 | * 313 | * @remarks 314 | * Generated from https://amp-api.apps.apple.com/v1/storefronts using ([this 315 | * script](https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1397015499)). 316 | */ 317 | export const allowedLanguagesPerCountryInMediaApi = { 318 | AF: ['en-GB'], 319 | AL: ['en-GB'], 320 | DZ: ['en-GB', 'fr-FR', 'ar'], 321 | AO: ['en-GB'], 322 | AI: ['en-GB'], 323 | AG: ['en-GB'], 324 | AR: ['es-MX', 'en-GB'], 325 | AM: ['en-GB'], 326 | AU: ['en-AU', 'en-GB'], 327 | AT: ['de-DE', 'en-GB'], 328 | AZ: ['en-GB'], 329 | BS: ['en-GB'], 330 | BH: ['en-GB', 'ar'], 331 | BB: ['en-GB'], 332 | BY: ['en-GB'], 333 | BE: ['en-GB', 'fr-FR', 'nl'], 334 | BZ: ['en-GB', 'es-MX'], 335 | BJ: ['en-GB', 'fr-FR'], 336 | BM: ['en-GB'], 337 | BT: ['en-GB'], 338 | BO: ['es-MX', 'en-GB'], 339 | BA: ['en-GB', 'hr'], 340 | BW: ['en-GB'], 341 | BR: ['pt-BR', 'en-GB'], 342 | VG: ['en-GB'], 343 | BN: ['en-GB'], 344 | BG: ['en-GB'], 345 | BF: ['en-GB', 'fr-FR'], 346 | KH: ['en-GB', 'fr-FR'], 347 | CM: ['fr-FR', 'en-GB'], 348 | CA: ['en-CA', 'fr-CA'], 349 | CV: ['en-GB'], 350 | KY: ['en-GB'], 351 | TD: ['en-GB', 'fr-FR'], 352 | CL: ['es-MX', 'en-GB'], 353 | CN: ['zh-Hans-CN', 'en-GB'], 354 | CO: ['es-MX', 'en-GB'], 355 | CR: ['es-MX', 'en-GB'], 356 | HR: ['en-GB', 'hr'], 357 | CY: ['en-GB', 'el', 'tr'], 358 | CZ: ['en-GB', 'cs'], 359 | CI: ['fr-FR', 'en-GB'], 360 | CD: ['en-GB', 'fr-FR'], 361 | DK: ['en-GB', 'da'], 362 | DM: ['en-GB'], 363 | DO: ['es-MX', 'en-GB'], 364 | EC: ['es-MX', 'en-GB'], 365 | EG: ['en-GB', 'fr-FR', 'ar'], 366 | SV: ['es-MX', 'en-GB'], 367 | EE: ['en-GB'], 368 | SZ: ['en-GB'], 369 | FJ: ['en-GB'], 370 | FI: ['en-GB', 'fi'], 371 | FR: ['fr-FR', 'en-GB'], 372 | GA: ['fr-FR', 'en-GB'], 373 | GM: ['en-GB'], 374 | GE: ['en-GB'], 375 | DE: ['de-DE', 'en-GB'], 376 | GH: ['en-GB'], 377 | GR: ['en-GB', 'el'], 378 | GD: ['en-GB'], 379 | GT: ['es-MX', 'en-GB'], 380 | GW: ['en-GB', 'fr-FR'], 381 | GY: ['en-GB', 'fr-FR'], 382 | HN: ['es-MX', 'en-GB'], 383 | HK: ['zh-Hant-HK', 'en-GB', 'zh-Hant-TW'], 384 | HU: ['en-GB', 'hu'], 385 | IS: ['en-GB'], 386 | IN: ['en-GB', 'hi'], 387 | ID: ['en-GB', 'id'], 388 | IQ: ['en-GB', 'ar'], 389 | IE: ['en-GB'], 390 | IL: ['en-GB', 'he'], 391 | IT: ['it', 'en-GB'], 392 | JM: ['en-GB'], 393 | JP: ['ja', 'en-US'], 394 | JO: ['en-GB', 'ar'], 395 | KZ: ['en-GB'], 396 | KE: ['en-GB'], 397 | KR: ['ko', 'en-GB'], 398 | XK: ['en-GB'], 399 | KW: ['en-GB', 'ar'], 400 | KG: ['en-GB'], 401 | LA: ['en-GB', 'fr-FR'], 402 | LV: ['en-GB'], 403 | LB: ['en-GB', 'fr-FR', 'ar'], 404 | LR: ['en-GB'], 405 | LY: ['en-GB', 'ar'], 406 | LT: ['en-GB'], 407 | LU: ['en-GB', 'fr-FR', 'de-DE'], 408 | MO: ['zh-Hant-HK', 'en-GB', 'zh-Hant-TW'], 409 | MG: ['en-GB', 'fr-FR'], 410 | MW: ['en-GB'], 411 | MY: ['en-GB', 'ms'], 412 | MV: ['en-GB'], 413 | ML: ['en-GB', 'fr-FR'], 414 | MT: ['en-GB'], 415 | MR: ['en-GB', 'fr-FR', 'ar'], 416 | MU: ['en-GB', 'fr-FR'], 417 | MX: ['es-MX', 'en-GB'], 418 | FM: ['en-GB'], 419 | MD: ['en-GB'], 420 | MN: ['en-GB'], 421 | ME: ['en-GB', 'hr'], 422 | MS: ['en-GB'], 423 | MA: ['en-GB', 'fr-FR', 'ar'], 424 | MZ: ['en-GB'], 425 | MM: ['en-GB'], 426 | NA: ['en-GB'], 427 | NR: ['en-GB'], 428 | NP: ['en-GB'], 429 | NL: ['nl', 'en-GB'], 430 | NZ: ['en-AU', 'en-GB'], 431 | NI: ['es-MX', 'en-GB'], 432 | NE: ['en-GB', 'fr-FR'], 433 | NG: ['en-GB'], 434 | MK: ['en-GB'], 435 | NO: ['en-GB', 'nb'], 436 | OM: ['en-GB', 'ar'], 437 | PK: ['en-GB'], 438 | PW: ['en-GB'], 439 | PA: ['es-MX', 'en-GB'], 440 | PG: ['en-GB'], 441 | PY: ['es-MX', 'en-GB'], 442 | PE: ['es-MX', 'en-GB'], 443 | PH: ['en-GB'], 444 | PL: ['en-GB', 'pl'], 445 | PT: ['pt-PT', 'en-GB'], 446 | QA: ['en-GB', 'ar'], 447 | CG: ['en-GB', 'fr-FR'], 448 | RO: ['en-GB', 'ro'], 449 | RU: ['ru', 'en-GB', 'uk'], 450 | RW: ['en-GB', 'fr-FR'], 451 | SA: ['en-GB', 'ar'], 452 | SN: ['en-GB', 'fr-FR'], 453 | RS: ['en-GB', 'hr'], 454 | SC: ['en-GB', 'fr-FR'], 455 | SL: ['en-GB'], 456 | SG: ['en-GB', 'zh-Hans-CN'], 457 | SK: ['en-GB', 'sk'], 458 | SI: ['en-GB'], 459 | SB: ['en-GB'], 460 | ZA: ['en-GB'], 461 | ES: ['es-ES', 'en-GB', 'ca'], 462 | LK: ['en-GB'], 463 | KN: ['en-GB'], 464 | LC: ['en-GB'], 465 | VC: ['en-GB'], 466 | SR: ['en-GB', 'nl'], 467 | SE: ['sv', 'en-GB'], 468 | CH: ['de-CH', 'de-DE', 'en-GB', 'fr-FR', 'it'], 469 | ST: ['en-GB'], 470 | TW: ['zh-Hant-TW', 'en-GB'], 471 | TJ: ['en-GB'], 472 | TZ: ['en-GB'], 473 | TH: ['en-GB', 'th'], 474 | TO: ['en-GB'], 475 | TT: ['en-GB', 'fr-FR'], 476 | TN: ['en-GB', 'fr-FR', 'ar'], 477 | TR: ['en-GB', 'tr'], 478 | TM: ['en-GB'], 479 | TC: ['en-GB'], 480 | AE: ['en-GB', 'ar'], 481 | UG: ['en-GB'], 482 | UA: ['en-GB', 'uk', 'ru'], 483 | GB: ['en-GB'], 484 | US: ['en-US', 'es-MX', 'ar', 'ru', 'zh-Hans-CN', 'fr-FR', 'ko', 'pt-BR', 'vi', 'zh-Hant-TW'], 485 | UY: ['en-GB', 'es-MX'], 486 | UZ: ['en-GB'], 487 | VU: ['en-GB', 'fr-FR'], 488 | VE: ['es-MX', 'en-GB'], 489 | VN: ['en-GB', 'vi'], 490 | YE: ['en-GB', 'ar'], 491 | ZM: ['en-GB'], 492 | ZW: ['en-GB'], 493 | } as const; 494 | /** The ISO 3166-1 alpha-2 code of a country supported by Apple's media API (amp-api.apps.apple.com). */ 495 | export type MediaApiCountry = keyof typeof allowedLanguagesPerCountryInMediaApi; 496 | /** 497 | * A type mapping from the ISO 3166-1 alpha-2 code of countries to the language codes that they support in Apple's media 498 | * API (amp-api.apps.apple.com). 499 | * 500 | * @see {@link allowedLanguagesPerCountryInMediaApi} 501 | */ 502 | export type AllowedLanguagesPerCountryInMediaApi = { 503 | [country in MediaApiCountry]: (typeof allowedLanguagesPerCountryInMediaApi)[country][number]; 504 | }; 505 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | parse-tunes 2 | 3 | # parse-tunes 4 | 5 | ## Table of contents 6 | 7 | ### Type Aliases 8 | 9 | - [AllowedLanguagesPerCountryInMediaApi](README.md#allowedlanguagespercountryinmediaapi) 10 | - [AppDetailsArtwork](README.md#appdetailsartwork) 11 | - [AppDetailsAvailableAttribute](README.md#appdetailsavailableattribute) 12 | - [AppDetailsPlatformInRequest](README.md#appdetailsplatforminrequest) 13 | - [AppDetailsPlatformInResponse](README.md#appdetailsplatforminresponse) 14 | - [AppDetailsPlatformInResponseForRequest](README.md#appdetailsplatforminresponseforrequest) 15 | - [AppDetailsRequest](README.md#appdetailsrequest) 16 | - [AppDetailsResponse](README.md#appdetailsresponse) 17 | - [AppDetailsResponseFragmentPerAttribute](README.md#appdetailsresponsefragmentperattribute) 18 | - [AppSearchRequest](README.md#appsearchrequest) 19 | - [AppSearchResponse](README.md#appsearchresponse) 20 | - [AppSearchReturnedAttribute](README.md#appsearchreturnedattribute) 21 | - [Chart](README.md#chart) 22 | - [Genre](README.md#genre) 23 | - [GenreName](README.md#genrename) 24 | - [MediaApiCountry](README.md#mediaapicountry) 25 | - [PlatformAttributes](README.md#platformattributes) 26 | - [PrivacyTypes](README.md#privacytypes) 27 | - [PrivacyTypesShort](README.md#privacytypesshort) 28 | - [StorefrontCountry](README.md#storefrontcountry) 29 | - [StorefrontCountryCode](README.md#storefrontcountrycode) 30 | - [StorefrontLanguage](README.md#storefrontlanguage) 31 | - [StorefrontLanguageCode](README.md#storefrontlanguagecode) 32 | - [StorefrontPlatform](README.md#storefrontplatform) 33 | - [StorefrontPlatformName](README.md#storefrontplatformname) 34 | - [TopChartRequest](README.md#topchartrequest) 35 | - [TopChartResult](README.md#topchartresult) 36 | 37 | ### Variables 38 | 39 | - [allowedLanguagesPerCountryInMediaApi](README.md#allowedlanguagespercountryinmediaapi-1) 40 | - [appDetailsAvailableAttributes](README.md#appdetailsavailableattributes) 41 | - [appDetailsTokenUrls](README.md#appdetailstokenurls) 42 | - [charts](README.md#charts) 43 | - [countries](README.md#countries) 44 | - [genres](README.md#genres) 45 | - [languages](README.md#languages) 46 | - [platforms](README.md#platforms) 47 | 48 | ### Functions 49 | 50 | - [fetchAppDetails](README.md#fetchappdetails) 51 | - [fetchMediaApiToken](README.md#fetchmediaapitoken) 52 | - [fetchTopApps](README.md#fetchtopapps) 53 | - [searchApps](README.md#searchapps) 54 | 55 | ## Type Aliases 56 | 57 | ### AllowedLanguagesPerCountryInMediaApi 58 | 59 | Ƭ **AllowedLanguagesPerCountryInMediaApi**: { [country in MediaApiCountry]: typeof allowedLanguagesPerCountryInMediaApi[country][number] } 60 | 61 | A type mapping from the ISO 3166-1 alpha-2 code of countries to the language codes that they support in Apple's media 62 | API (amp-api.apps.apple.com). 63 | 64 | **`See`** 65 | 66 | [allowedLanguagesPerCountryInMediaApi](README.md#allowedlanguagespercountryinmediaapi-1) 67 | 68 | #### Defined in 69 | 70 | [common/consts.ts:502](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L502) 71 | 72 | ___ 73 | 74 | ### AppDetailsArtwork 75 | 76 | Ƭ **AppDetailsArtwork**: `Object` 77 | 78 | An artwork image in a response fragment. 79 | 80 | #### Type declaration 81 | 82 | | Name | Type | 83 | | :------ | :------ | 84 | | `bgColor` | `string` | 85 | | `height` | `number` | 86 | | `textColor1` | `string` | 87 | | `textColor2` | `string` | 88 | | `textColor3` | `string` | 89 | | `textColor4` | `string` | 90 | | `url` | `string` | 91 | | `width` | `number` | 92 | 93 | #### Defined in 94 | 95 | [common/app-meta.ts:123](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L123) 96 | 97 | ___ 98 | 99 | ### AppDetailsAvailableAttribute 100 | 101 | Ƭ **AppDetailsAvailableAttribute**: typeof [`appDetailsAvailableAttributes`](README.md#appdetailsavailableattributes)[`number`] 102 | 103 | An attribute (field) that can be requested from the app details endpoint. 104 | 105 | #### Defined in 106 | 107 | [common/app-meta.ts:84](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L84) 108 | 109 | ___ 110 | 111 | ### AppDetailsPlatformInRequest 112 | 113 | Ƭ **AppDetailsPlatformInRequest**: ``"web"`` \| ``"iphone"`` \| ``"appletv"`` \| ``"ipad"`` \| ``"mac"`` \| ``"watch"`` 114 | 115 | A platform that can appear in the `platform` or `additionalPlatforms` parameter of a request to the app details or 116 | search endpoint. 117 | 118 | #### Defined in 119 | 120 | [common/app-meta.ts:92](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L92) 121 | 122 | ___ 123 | 124 | ### AppDetailsPlatformInResponse 125 | 126 | Ƭ **AppDetailsPlatformInResponse**: [`AppDetailsPlatformInResponseForRequest`](README.md#appdetailsplatforminresponseforrequest)[keyof [`AppDetailsPlatformInResponseForRequest`](README.md#appdetailsplatforminresponseforrequest)] 127 | 128 | A platform that can appear in the response from the app details or search endpoint as a key of the 129 | `platformAttributes` object. 130 | 131 | **`See`** 132 | 133 | [https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1400240548](https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1400240548) 134 | 135 | #### Defined in 136 | 137 | [common/app-meta.ts:113](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L113) 138 | 139 | ___ 140 | 141 | ### AppDetailsPlatformInResponseForRequest 142 | 143 | Ƭ **AppDetailsPlatformInResponseForRequest**: `Object` 144 | 145 | A type mapping from the platforms that can appear in a request to the app details or search endpoint to the key of 146 | the `platformAttributes` object in the response that they cause to be included. 147 | 148 | **`See`** 149 | 150 | [https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1400240548](https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1400240548) 151 | 152 | #### Type declaration 153 | 154 | | Name | Type | 155 | | :------ | :------ | 156 | | `appletv` | ``"appletvos"`` | 157 | | `ipad` | ``"ios"`` | 158 | | `iphone` | ``"ios"`` | 159 | | `mac` | ``"osx"`` | 160 | | `watch` | ``"ios"`` | 161 | | `web` | `undefined` | 162 | 163 | #### Defined in 164 | 165 | [common/app-meta.ts:99](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L99) 166 | 167 | ___ 168 | 169 | ### AppDetailsRequest 170 | 171 | Ƭ **AppDetailsRequest**<`Country`, `Platforms`, `Attributes`\>: `Object` 172 | 173 | Parameters for an app details request. 174 | 175 | #### Type parameters 176 | 177 | | Name | Type | 178 | | :------ | :------ | 179 | | `Country` | extends [`MediaApiCountry`](README.md#mediaapicountry) | 180 | | `Platforms` | extends [`AppDetailsPlatformInRequest`](README.md#appdetailsplatforminrequest)[] | 181 | | `Attributes` | extends [`AppDetailsAvailableAttribute`](README.md#appdetailsavailableattribute)[] | 182 | 183 | #### Type declaration 184 | 185 | | Name | Type | Description | 186 | | :------ | :------ | :------ | 187 | | `appId` | `number` | The numerical ID of the app for which to fetch the details. | 188 | | `attributes` | `Attributes` | The attributes to fetch. See [appDetailsAvailableAttributes](README.md#appdetailsavailableattributes) for a list. | 189 | | `country` | `Country` | Which country's App Store to use. | 190 | | `language` | [`AllowedLanguagesPerCountryInMediaApi`](README.md#allowedlanguagespercountryinmediaapi)[`Country`] | The language in which to fetch the details. | 191 | | `platforms?` | `Platforms` | The platform(s) for which to fetch details about the requested app. Will fetch details for all platforms if this parameter isn't specified. | 192 | | `token?` | `string` | The token to use for authentication. If you don't provide one, it will be fetched automatically. However, if you want to fetch the details for multiple apps, it's recommended to fetch the token once and then pass it to all the requests instead of re-fetching the token for each request. You can use [fetchMediaApiToken](README.md#fetchmediaapitoken) to fetch a token beforehand. | 193 | 194 | #### Defined in 195 | 196 | [endpoints/app-details.ts:58](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/app-details.ts#L58) 197 | 198 | ___ 199 | 200 | ### AppDetailsResponse 201 | 202 | Ƭ **AppDetailsResponse**<`Platforms`, `Attributes`\>: `UnionToIntersection`<[`AppDetailsResponseFragmentPerAttribute`](README.md#appdetailsresponsefragmentperattribute)<`Platforms`\>[`Attributes`]\> 203 | 204 | The response from the app details API, typed according to the attributes specified in the request. 205 | 206 | Note: There is no publicly available documentation for the API responses. The types were extrapolated from a few 207 | tested responses. They may not be 100 % accurate. 208 | 209 | #### Type parameters 210 | 211 | | Name | Type | 212 | | :------ | :------ | 213 | | `Platforms` | extends [`AppDetailsPlatformInResponse`](README.md#appdetailsplatforminresponse) | 214 | | `Attributes` | extends [`AppDetailsAvailableAttribute`](README.md#appdetailsavailableattribute) | 215 | 216 | #### Defined in 217 | 218 | [endpoints/app-details.ts:108](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/app-details.ts#L108) 219 | 220 | ___ 221 | 222 | ### AppDetailsResponseFragmentPerAttribute 223 | 224 | Ƭ **AppDetailsResponseFragmentPerAttribute**<`Platforms`\>: `Object` 225 | 226 | Type mapping from the possible attributes to the additional data they add in the response. 227 | 228 | #### Type parameters 229 | 230 | | Name | Type | 231 | | :------ | :------ | 232 | | `Platforms` | extends [`AppDetailsPlatformInResponse`](README.md#appdetailsplatforminresponse) | 233 | 234 | #### Type declaration 235 | 236 | | Name | Type | 237 | | :------ | :------ | 238 | | `artistName` | { `artistName`: `string` } | 239 | | `artistName.artistName` | `string` | 240 | | `artwork` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `artwork`: [`AppDetailsArtwork`](README.md#appdetailsartwork) }\> | 241 | | `bundleId` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `bundleId`: `string` }\> | 242 | | `chartPositions` | { `chartPositions?`: { [store in "appStore" \| "messages"]?: Object } } | 243 | | `chartPositions.chartPositions?` | { [store in "appStore" \| "messages"]?: Object } | 244 | | `contentRatingsBySystem` | { `contentRatingsBySystem`: { `appsApple`: { `advisories?`: `string`[] ; `name`: `string` ; `rank`: `number` ; `value`: `number` } } } | 245 | | `contentRatingsBySystem.contentRatingsBySystem` | { `appsApple`: { `advisories?`: `string`[] ; `name`: `string` ; `rank`: `number` ; `value`: `number` } } | 246 | | `contentRatingsBySystem.contentRatingsBySystem.appsApple` | { `advisories?`: `string`[] ; `name`: `string` ; `rank`: `number` ; `value`: `number` } | 247 | | `contentRatingsBySystem.contentRatingsBySystem.appsApple.advisories?` | `string`[] | 248 | | `contentRatingsBySystem.contentRatingsBySystem.appsApple.name` | `string` | 249 | | `contentRatingsBySystem.contentRatingsBySystem.appsApple.rank` | `number` | 250 | | `contentRatingsBySystem.contentRatingsBySystem.appsApple.value` | `number` | 251 | | `copyright` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `copyright`: `string` }\> | 252 | | `customArtwork` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `customAttributes`: { `default`: { `default`: { `customArtwork`: [`AppDetailsArtwork`](README.md#appdetailsartwork) } } } }\> | 253 | | `customScreenshotsByType` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `customAttributes`: { `default`: { `default`: { `customScreenshotsByType`: { `[device: string]`: [`AppDetailsArtwork`](README.md#appdetailsartwork)[]; } } } } }\> | 254 | | `customVideoPreviewsByType` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `customAttributes`: { `default`: { `default`: { `customVideoPreviewsByType`: { `[device: string]`: { `previewFrame`: [`AppDetailsArtwork`](README.md#appdetailsartwork) ; `video`: `string` }[]; } } } } }\> | 255 | | `description` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `description`: { `standard`: `string` } }\> | 256 | | `deviceFamilies` | { `deviceFamilies`: `string`[] } | 257 | | `deviceFamilies.deviceFamilies` | `string`[] | 258 | | `editorialArtwork` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `editorialArtwork`: `Record`<`string`, [`AppDetailsArtwork`](README.md#appdetailsartwork)\> }\> | 259 | | `eula` | { `eula`: `string` } | 260 | | `eula.eula` | `string` | 261 | | `externalVersionId` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `externalVersionId`: `number` }\> | 262 | | `familyShareEnabledDate` | { `familyShareEnabledDate`: `string` } | 263 | | `familyShareEnabledDate.familyShareEnabledDate` | `string` | 264 | | `fileSizeByDevice` | { `fileSizeByDevice`: { `[device: string]`: `number`; } } | 265 | | `fileSizeByDevice.fileSizeByDevice` | { `[device: string]`: `number`; } | 266 | | `genreDisplayName` | { `genreDisplayName`: [`GenreName`](README.md#genrename) } | 267 | | `genreDisplayName.genreDisplayName` | [`GenreName`](README.md#genrename) | 268 | | `hasEula` | { `hasEula`: `boolean` } | 269 | | `hasEula.hasEula` | `boolean` | 270 | | `hasFamilyShareableInAppPurchases` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `hasFamilyShareableInAppPurchases`: `boolean` }\> | 271 | | `hasInAppPurchases` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `hasInAppPurchases`: `boolean` }\> | 272 | | `hasMessagesExtension` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `hasMessagesExtension`: `boolean` }\> | 273 | | `hasPrivacyPolicyText` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `hasPrivacyPolicyText`: `boolean` }\> | 274 | | `hasSafariExtension` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `hasSafariExtension`: `boolean` }\> | 275 | | `is32bitOnly` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `is32bitOnly`: `boolean` }\> | 276 | | `isAppleWatchSupported` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `isAppleWatchSupported`: `boolean` }\> | 277 | | `isDeliveredInIOSAppForWatchOS` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `isDeliveredInIOSAppForWatchOS`: `boolean` }\> | 278 | | `isFirstPartyHideableApp` | { `isFirstPartyHideableApp`: `boolean` } | 279 | | `isFirstPartyHideableApp.isFirstPartyHideableApp` | `boolean` | 280 | | `isGameCenterEnabled` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `isGameCenterEnabled`: `boolean` }\> | 281 | | `isHiddenFromSpringboard` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `isHiddenFromSpringboard`: `boolean` }\> | 282 | | `isIOSBinaryMacOSCompatible` | { `isIOSBinaryMacOSCompatible`: `boolean` } | 283 | | `isIOSBinaryMacOSCompatible.isIOSBinaryMacOSCompatible` | `boolean` | 284 | | `isPreorder` | { `isPreorder`: `boolean` } | 285 | | `isPreorder.isPreorder` | `boolean` | 286 | | `isSiriSupported` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `isSiriSupported`: `boolean` }\> | 287 | | `isStandaloneForWatchOS` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `isStandaloneForWatchOS`: `boolean` }\> | 288 | | `isStandaloneWithCompanionForWatchOS` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `isStandaloneWithCompanionForWatchOS`: `boolean` }\> | 289 | | `languageList` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `languageList`: `string`[] }\> | 290 | | `maxPlayers` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `maxPlayers`: `number` }\> | 291 | | `messagesScreenshots` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `messagesScreenshots?`: { `[device: string]`: [`AppDetailsArtwork`](README.md#appdetailsartwork); } }\> | 292 | | `minPlayers` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `minPlayers`: `number` }\> | 293 | | `minimumMacOSVersion` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `minimumMacOSVersion`: `string` }\> | 294 | | `minimumOSVersion` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `minimumOSVersion`: `string` }\> | 295 | | `name` | { `name`: `string` } | 296 | | `name.name` | `string` | 297 | | `offers` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `offers`: { `assets`: { `flavor`: `string` ; `size`: `number` }[] ; `buyParams`: `string` ; `currencyCode`: `string` ; `price`: `number` ; `priceFormatted`: `string` ; `type`: `string` }[] }\> | 298 | | `privacy` | { `privacy`: { `privacyTypes`: [`PrivacyTypesShort`](README.md#privacytypesshort) } } | 299 | | `privacy.privacy` | { `privacyTypes`: [`PrivacyTypesShort`](README.md#privacytypesshort) } | 300 | | `privacy.privacy.privacyTypes` | [`PrivacyTypesShort`](README.md#privacytypesshort) | 301 | | `privacyDetails` | { `privacyDetails`: { `managePrivacyChoicesUrl`: `string` \| ``null`` ; `privacyTypes`: [`PrivacyTypes`](README.md#privacytypes) } } | 302 | | `privacyDetails.privacyDetails` | { `managePrivacyChoicesUrl`: `string` \| ``null`` ; `privacyTypes`: [`PrivacyTypes`](README.md#privacytypes) } | 303 | | `privacyDetails.privacyDetails.managePrivacyChoicesUrl` | `string` \| ``null`` | 304 | | `privacyDetails.privacyDetails.privacyTypes` | [`PrivacyTypes`](README.md#privacytypes) | 305 | | `privacyPolicyText` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `privacyPolicyText`: `string` }\> | 306 | | `privacyPolicyUrl` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `privacyPolicyUrl`: `string` }\> | 307 | | `releaseDate` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `releaseDate`: `string` }\> | 308 | | `remoteControllerRequirement` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `remoteControllerRequirement`: `string` }\> | 309 | | `requiredCapabilities` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `requiredCapabilities`: `string` }\> | 310 | | `requirementsByDeviceFamily` | { `requirementsByDeviceFamily`: { `[device: string]`: { `deviceFamily`: `string` ; `requirementsString`: `string` }; } } | 311 | | `requirementsByDeviceFamily.requirementsByDeviceFamily` | { `[device: string]`: { `deviceFamily`: `string` ; `requirementsString`: `string` }; } | 312 | | `requirementsString` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `requirementsString`: `string` }\> | 313 | | `requires32bit` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `requires32bit`: `boolean` }\> | 314 | | `requiresGameController` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `requiresGameController`: `boolean` }\> | 315 | | `reviewsRestricted` | { `reviewsRestricted`: `boolean` } | 316 | | `reviewsRestricted.reviewsRestricted` | `boolean` | 317 | | `seller` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `seller`: `string` }\> | 318 | | `sellerLabel` | { `sellerLabel`: `string` } | 319 | | `sellerLabel.sellerLabel` | `string` | 320 | | `supportURLForLanguage` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `supportURLForLanguage`: `string` }\> | 321 | | `supportedLocales` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `supportedLocales`: { `name`: `string` ; `tag`: `string` }[] }\> | 322 | | `supportsArcade` | { `supportsArcade`: `boolean` } | 323 | | `supportsArcade.supportsArcade` | `boolean` | 324 | | `supportsFunCamera` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `supportsFunCamera`: `boolean` }\> | 325 | | `supportsGameController` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `supportsGameController`: `boolean` }\> | 326 | | `supportsPassbook` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `supportsPassbook`: `boolean` }\> | 327 | | `url` | { `url`: `string` } | 328 | | `url.url` | `string` | 329 | | `userRating` | { `userRating`: { `ariaLabelForRating`: `string` ; `ratingCount`: `number` ; `ratingCountList`: [`number`, `number`, `number`, `number`, `number`] ; `value`: `number` } } | 330 | | `userRating.userRating` | { `ariaLabelForRating`: `string` ; `ratingCount`: `number` ; `ratingCountList`: [`number`, `number`, `number`, `number`, `number`] ; `value`: `number` } | 331 | | `userRating.userRating.ariaLabelForRating` | `string` | 332 | | `userRating.userRating.ratingCount` | `number` | 333 | | `userRating.userRating.ratingCountList` | [`number`, `number`, `number`, `number`, `number`] | 334 | | `userRating.userRating.value` | `number` | 335 | | `usesLocationBackgroundMode` | { `usesLocationBackgroundMode`: `boolean` } | 336 | | `usesLocationBackgroundMode.usesLocationBackgroundMode` | `boolean` | 337 | | `versionHistory` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `versionHistory`: { `releaseDate`: `string` ; `releaseNotes`: `string` ; `releaseTimestamp`: `string` ; `versionDisplay`: `string` }[] }\> | 338 | | `websiteUrl` | [`PlatformAttributes`](README.md#platformattributes)<`Platforms`, { `websiteUrl`: `string` }\> | 339 | 340 | #### Defined in 341 | 342 | [common/app-meta.ts:167](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L167) 343 | 344 | ___ 345 | 346 | ### AppSearchRequest 347 | 348 | Ƭ **AppSearchRequest**<`Country`, `Platforms`\>: `Object` 349 | 350 | Parameters for an app search request. 351 | 352 | #### Type parameters 353 | 354 | | Name | Type | 355 | | :------ | :------ | 356 | | `Country` | extends [`MediaApiCountry`](README.md#mediaapicountry) | 357 | | `Platforms` | extends [`AppDetailsPlatformInRequest`](README.md#appdetailsplatforminrequest)[] | 358 | 359 | #### Type declaration 360 | 361 | | Name | Type | Description | 362 | | :------ | :------ | :------ | 363 | | `country` | `Country` | Which country's App Store to use. | 364 | | `language` | [`AllowedLanguagesPerCountryInMediaApi`](README.md#allowedlanguagespercountryinmediaapi)[`Country`] | The language in which to fetch the app details. | 365 | | `platforms?` | `Platforms` | The platform(s) for which to fetch details about the found apps. Will fetch details for all platforms if this parameter isn't specified. | 366 | | `searchTerm` | `string` | The term to search for. | 367 | 368 | #### Defined in 369 | 370 | [endpoints/search.ts:12](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/search.ts#L12) 371 | 372 | ___ 373 | 374 | ### AppSearchResponse 375 | 376 | Ƭ **AppSearchResponse**<`Platforms`\>: `UnionToIntersection`<[`AppDetailsResponseFragmentPerAttribute`](README.md#appdetailsresponsefragmentperattribute)<`Platforms`\>[[`AppSearchReturnedAttribute`](README.md#appsearchreturnedattribute)]\>[] 377 | 378 | The response from the app search API. 379 | 380 | Note: There is no publicly available documentation for the API responses. The types were extrapolated from a few 381 | tested responses. They may not be 100 % accurate. 382 | 383 | #### Type parameters 384 | 385 | | Name | Type | 386 | | :------ | :------ | 387 | | `Platforms` | extends [`AppDetailsPlatformInResponse`](README.md#appdetailsplatforminresponse) | 388 | 389 | #### Defined in 390 | 391 | [endpoints/search.ts:99](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/search.ts#L99) 392 | 393 | ___ 394 | 395 | ### AppSearchReturnedAttribute 396 | 397 | Ƭ **AppSearchReturnedAttribute**: ``"supportsArcade"`` \| ``"familyShareEnabledDate"`` \| ``"isFirstPartyHideableApp"`` \| ``"contentRatingsBySystem"`` \| ``"deviceFamilies"`` \| ``"chartPositions"`` \| ``"url"`` \| ``"usesLocationBackgroundMode"`` \| ``"userRating"`` \| ``"name"`` \| ``"genreDisplayName"`` \| ``"isPreorder"`` \| ``"isIOSBinaryMacOSCompatible"`` \| ``"artistName"`` \| ``"reviewsRestricted"`` \| ``"sellerLabel"`` \| ``"hasEula"`` \| ``"seller"`` \| ``"copyright"`` \| ``"minimumMacOSVersion"`` \| ``"isStandaloneWithCompanionForWatchOS"`` \| ``"isAppleWatchSupported"`` \| ``"is32bitOnly"`` \| ``"hasSafariExtension"`` \| ``"languageList"`` \| ``"requiresGameController"`` \| ``"requiredCapabilities"`` \| ``"offers"`` \| ``"supportedLocales"`` \| ``"requires32bit"`` \| ``"isSiriSupported"`` \| ``"isGameCenterEnabled"`` \| ``"releaseDate"`` \| ``"minimumOSVersion"`` \| ``"hasInAppPurchases"`` \| ``"bundleId"`` \| ``"hasMessagesExtension"`` \| ``"supportsGameController"`` \| ``"artwork"`` \| ``"hasFamilyShareableInAppPurchases"`` \| ``"isStandaloneForWatchOS"`` \| ``"isHiddenFromSpringboard"`` \| ``"isDeliveredInIOSAppForWatchOS"`` \| ``"hasPrivacyPolicyText"`` \| ``"editorialArtwork"`` \| ``"supportsPassbook"`` \| ``"requirementsString"`` \| ``"externalVersionId"`` 398 | 399 | The attributes that are returned in the app search response. 400 | 401 | These are currently not configurable. 402 | 403 | #### Defined in 404 | 405 | [endpoints/search.ts:43](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/search.ts#L43) 406 | 407 | ___ 408 | 409 | ### Chart 410 | 411 | Ƭ **Chart**: typeof [`charts`](README.md#charts)[keyof typeof [`charts`](README.md#charts)] 412 | 413 | The `popId` of a chart on the App Store. 414 | 415 | #### Defined in 416 | 417 | [endpoints/top-charts.ts:18](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/top-charts.ts#L18) 418 | 419 | ___ 420 | 421 | ### Genre 422 | 423 | Ƭ **Genre**: typeof [`genres`](README.md#genres)[keyof typeof [`genres`](README.md#genres)] 424 | 425 | The ID of a genre or subgenre on the App Store. 426 | 427 | #### Defined in 428 | 429 | [common/consts.ts:305](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L305) 430 | 431 | ___ 432 | 433 | ### GenreName 434 | 435 | Ƭ **GenreName**: keyof typeof [`genres`](README.md#genres) 436 | 437 | The name of a genre or subgenre on the App Store. 438 | 439 | #### Defined in 440 | 441 | [common/consts.ts:307](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L307) 442 | 443 | ___ 444 | 445 | ### MediaApiCountry 446 | 447 | Ƭ **MediaApiCountry**: keyof typeof [`allowedLanguagesPerCountryInMediaApi`](README.md#allowedlanguagespercountryinmediaapi-1) 448 | 449 | The ISO 3166-1 alpha-2 code of a country supported by Apple's media API (amp-api.apps.apple.com). 450 | 451 | #### Defined in 452 | 453 | [common/consts.ts:495](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L495) 454 | 455 | ___ 456 | 457 | ### PlatformAttributes 458 | 459 | Ƭ **PlatformAttributes**<`Platforms`, `ResponseFragment`\>: `Object` 460 | 461 | Small helper for response fragments that are listed under `platformAttributes`. 462 | 463 | #### Type parameters 464 | 465 | | Name | Type | 466 | | :------ | :------ | 467 | | `Platforms` | extends [`AppDetailsPlatformInResponse`](README.md#appdetailsplatforminresponse) | 468 | | `ResponseFragment` | `ResponseFragment` | 469 | 470 | #### Type declaration 471 | 472 | | Name | Type | 473 | | :------ | :------ | 474 | | `platformAttributes` | { [key in Exclude]?: ResponseFragment } | 475 | 476 | #### Defined in 477 | 478 | [common/app-meta.ts:117](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L117) 479 | 480 | ___ 481 | 482 | ### PrivacyTypes 483 | 484 | Ƭ **PrivacyTypes**: { `dataCategories`: { `dataCategory`: `string` ; `dataTypes`: `string`[] ; `identifier`: `string` }[] ; `description`: `string` ; `identifier`: ``"DATA_NOT_COLLECTED"`` \| ``"DATA_USED_TO_TRACK_YOU"`` \| ``"DATA_LINKED_TO_YOU"`` \| ``"DATA_NOT_LINKED_TO_YOU"`` ; `privacyType`: `string` ; `purposes`: { `dataCategories`: { `dataCategory`: `string` ; `dataTypes`: `string`[] ; `identifier`: `string` }[] ; `identifier`: `string` ; `purpose`: `string` }[] }[] 485 | 486 | A list of privacy types as declared in a privacy label, in long format as returned for the `privacyDetails` 487 | attribute. 488 | 489 | #### Defined in 490 | 491 | [common/app-meta.ts:147](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L147) 492 | 493 | ___ 494 | 495 | ### PrivacyTypesShort 496 | 497 | Ƭ **PrivacyTypesShort**: { `dataCategories`: { `dataCategory`: `string` ; `identifier`: `string` }[] ; `description`: `string` ; `identifier`: ``"DATA_NOT_COLLECTED"`` \| ``"DATA_USED_TO_TRACK_YOU"`` \| ``"DATA_LINKED_TO_YOU"`` \| ``"DATA_NOT_LINKED_TO_YOU"`` ; `privacyType`: `string` }[] 498 | 499 | A list of privacy types as declared in a privacy label, in short format as returned for the `privacy` attribute. 500 | 501 | #### Defined in 502 | 503 | [common/app-meta.ts:134](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L134) 504 | 505 | ___ 506 | 507 | ### StorefrontCountry 508 | 509 | Ƭ **StorefrontCountry**: typeof [`countries`](README.md#countries)[keyof typeof [`countries`](README.md#countries)] 510 | 511 | The ID of a country that can appear as the first parameter for the `X-Apple-Store-Front` header in a request to an 512 | iTunes endpoint. 513 | 514 | #### Defined in 515 | 516 | [common/consts.ts:146](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L146) 517 | 518 | ___ 519 | 520 | ### StorefrontCountryCode 521 | 522 | Ƭ **StorefrontCountryCode**: keyof typeof [`countries`](README.md#countries) 523 | 524 | The ISO 3166-1 alpha-2 code of a country that can appear as the first parameter for the `X-Apple-Store-Front` header 525 | in a request to an iTunes endpoint. 526 | 527 | #### Defined in 528 | 529 | [common/consts.ts:151](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L151) 530 | 531 | ___ 532 | 533 | ### StorefrontLanguage 534 | 535 | Ƭ **StorefrontLanguage**: typeof [`languages`](README.md#languages)[keyof typeof [`languages`](README.md#languages)] 536 | 537 | The ID of a language that can appear as the second parameter for the `X-Apple-Store-Front` header in a request to an 538 | iTunes endpoint. 539 | 540 | #### Defined in 541 | 542 | [common/consts.ts:212](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L212) 543 | 544 | ___ 545 | 546 | ### StorefrontLanguageCode 547 | 548 | Ƭ **StorefrontLanguageCode**: keyof typeof [`languages`](README.md#languages) 549 | 550 | The ISO 639-1 code of a language that can appear as the second parameter for the `X-Apple-Store-Front` header in a 551 | request to an iTunes endpoint. 552 | 553 | #### Defined in 554 | 555 | [common/consts.ts:217](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L217) 556 | 557 | ___ 558 | 559 | ### StorefrontPlatform 560 | 561 | Ƭ **StorefrontPlatform**: typeof [`platforms`](README.md#platforms)[keyof typeof [`platforms`](README.md#platforms)] 562 | 563 | The ID of a platform that can appear as the third parameter for the `X-Apple-Store-Front` header in a request to an 564 | iTunes endpoint. The list is not complete. 565 | 566 | #### Defined in 567 | 568 | [common/consts.ts:260](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L260) 569 | 570 | ___ 571 | 572 | ### StorefrontPlatformName 573 | 574 | Ƭ **StorefrontPlatformName**: keyof typeof [`platforms`](README.md#platforms) 575 | 576 | The internal name of a platform that can appear as the third parameter for the `X-Apple-Store-Front` header in a 577 | request to an iTunes endpoint. The list is not complete. 578 | 579 | #### Defined in 580 | 581 | [common/consts.ts:265](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L265) 582 | 583 | ___ 584 | 585 | ### TopChartRequest 586 | 587 | Ƭ **TopChartRequest**: `Object` 588 | 589 | Parameters for a top chart request. 590 | 591 | #### Type declaration 592 | 593 | | Name | Type | Description | 594 | | :------ | :------ | :------ | 595 | | `chart` | [`Chart`](README.md#chart) | The chart of top apps to fetch. **`See`** [charts](README.md#charts) | 596 | | `country` | [`StorefrontCountry`](README.md#storefrontcountry) | The country for which to fetch the respective top chart. **`See`** [countries](README.md#countries) | 597 | | `genre` | [`Genre`](README.md#genre) | The genre (category) for which to fetch the top apps. **`See`** [genres](README.md#genres) | 598 | 599 | #### Defined in 600 | 601 | [endpoints/top-charts.ts:21](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/top-charts.ts#L21) 602 | 603 | ___ 604 | 605 | ### TopChartResult 606 | 607 | Ƭ **TopChartResult**: `string`[] 608 | 609 | A list of the app IDs of the apps on the requested top chart. 610 | 611 | #### Defined in 612 | 613 | [endpoints/top-charts.ts:31](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/top-charts.ts#L31) 614 | 615 | ## Variables 616 | 617 | ### allowedLanguagesPerCountryInMediaApi 618 | 619 | • `Const` **allowedLanguagesPerCountryInMediaApi**: `Object` 620 | 621 | A mapping from the ISO 3166-1 alpha-2 code of countries to the language codes that they support in Apple's media API 622 | (amp-api.apps.apple.com). 623 | 624 | **`Remarks`** 625 | 626 | Generated from https://amp-api.apps.apple.com/v1/storefronts using ([this 627 | script](https://github.com/tweaselORG/parse-tunes/issues/6#issuecomment-1397015499)). 628 | 629 | #### Type declaration 630 | 631 | | Name | Type | 632 | | :------ | :------ | 633 | | `AE` | readonly [``"en-GB"``, ``"ar"``] | 634 | | `AF` | readonly [``"en-GB"``] | 635 | | `AG` | readonly [``"en-GB"``] | 636 | | `AI` | readonly [``"en-GB"``] | 637 | | `AL` | readonly [``"en-GB"``] | 638 | | `AM` | readonly [``"en-GB"``] | 639 | | `AO` | readonly [``"en-GB"``] | 640 | | `AR` | readonly [``"es-MX"``, ``"en-GB"``] | 641 | | `AT` | readonly [``"de-DE"``, ``"en-GB"``] | 642 | | `AU` | readonly [``"en-AU"``, ``"en-GB"``] | 643 | | `AZ` | readonly [``"en-GB"``] | 644 | | `BA` | readonly [``"en-GB"``, ``"hr"``] | 645 | | `BB` | readonly [``"en-GB"``] | 646 | | `BE` | readonly [``"en-GB"``, ``"fr-FR"``, ``"nl"``] | 647 | | `BF` | readonly [``"en-GB"``, ``"fr-FR"``] | 648 | | `BG` | readonly [``"en-GB"``] | 649 | | `BH` | readonly [``"en-GB"``, ``"ar"``] | 650 | | `BJ` | readonly [``"en-GB"``, ``"fr-FR"``] | 651 | | `BM` | readonly [``"en-GB"``] | 652 | | `BN` | readonly [``"en-GB"``] | 653 | | `BO` | readonly [``"es-MX"``, ``"en-GB"``] | 654 | | `BR` | readonly [``"pt-BR"``, ``"en-GB"``] | 655 | | `BS` | readonly [``"en-GB"``] | 656 | | `BT` | readonly [``"en-GB"``] | 657 | | `BW` | readonly [``"en-GB"``] | 658 | | `BY` | readonly [``"en-GB"``] | 659 | | `BZ` | readonly [``"en-GB"``, ``"es-MX"``] | 660 | | `CA` | readonly [``"en-CA"``, ``"fr-CA"``] | 661 | | `CD` | readonly [``"en-GB"``, ``"fr-FR"``] | 662 | | `CG` | readonly [``"en-GB"``, ``"fr-FR"``] | 663 | | `CH` | readonly [``"de-CH"``, ``"de-DE"``, ``"en-GB"``, ``"fr-FR"``, ``"it"``] | 664 | | `CI` | readonly [``"fr-FR"``, ``"en-GB"``] | 665 | | `CL` | readonly [``"es-MX"``, ``"en-GB"``] | 666 | | `CM` | readonly [``"fr-FR"``, ``"en-GB"``] | 667 | | `CN` | readonly [``"zh-Hans-CN"``, ``"en-GB"``] | 668 | | `CO` | readonly [``"es-MX"``, ``"en-GB"``] | 669 | | `CR` | readonly [``"es-MX"``, ``"en-GB"``] | 670 | | `CV` | readonly [``"en-GB"``] | 671 | | `CY` | readonly [``"en-GB"``, ``"el"``, ``"tr"``] | 672 | | `CZ` | readonly [``"en-GB"``, ``"cs"``] | 673 | | `DE` | readonly [``"de-DE"``, ``"en-GB"``] | 674 | | `DK` | readonly [``"en-GB"``, ``"da"``] | 675 | | `DM` | readonly [``"en-GB"``] | 676 | | `DO` | readonly [``"es-MX"``, ``"en-GB"``] | 677 | | `DZ` | readonly [``"en-GB"``, ``"fr-FR"``, ``"ar"``] | 678 | | `EC` | readonly [``"es-MX"``, ``"en-GB"``] | 679 | | `EE` | readonly [``"en-GB"``] | 680 | | `EG` | readonly [``"en-GB"``, ``"fr-FR"``, ``"ar"``] | 681 | | `ES` | readonly [``"es-ES"``, ``"en-GB"``, ``"ca"``] | 682 | | `FI` | readonly [``"en-GB"``, ``"fi"``] | 683 | | `FJ` | readonly [``"en-GB"``] | 684 | | `FM` | readonly [``"en-GB"``] | 685 | | `FR` | readonly [``"fr-FR"``, ``"en-GB"``] | 686 | | `GA` | readonly [``"fr-FR"``, ``"en-GB"``] | 687 | | `GB` | readonly [``"en-GB"``] | 688 | | `GD` | readonly [``"en-GB"``] | 689 | | `GE` | readonly [``"en-GB"``] | 690 | | `GH` | readonly [``"en-GB"``] | 691 | | `GM` | readonly [``"en-GB"``] | 692 | | `GR` | readonly [``"en-GB"``, ``"el"``] | 693 | | `GT` | readonly [``"es-MX"``, ``"en-GB"``] | 694 | | `GW` | readonly [``"en-GB"``, ``"fr-FR"``] | 695 | | `GY` | readonly [``"en-GB"``, ``"fr-FR"``] | 696 | | `HK` | readonly [``"zh-Hant-HK"``, ``"en-GB"``, ``"zh-Hant-TW"``] | 697 | | `HN` | readonly [``"es-MX"``, ``"en-GB"``] | 698 | | `HR` | readonly [``"en-GB"``, ``"hr"``] | 699 | | `HU` | readonly [``"en-GB"``, ``"hu"``] | 700 | | `ID` | readonly [``"en-GB"``, ``"id"``] | 701 | | `IE` | readonly [``"en-GB"``] | 702 | | `IL` | readonly [``"en-GB"``, ``"he"``] | 703 | | `IN` | readonly [``"en-GB"``, ``"hi"``] | 704 | | `IQ` | readonly [``"en-GB"``, ``"ar"``] | 705 | | `IS` | readonly [``"en-GB"``] | 706 | | `IT` | readonly [``"it"``, ``"en-GB"``] | 707 | | `JM` | readonly [``"en-GB"``] | 708 | | `JO` | readonly [``"en-GB"``, ``"ar"``] | 709 | | `JP` | readonly [``"ja"``, ``"en-US"``] | 710 | | `KE` | readonly [``"en-GB"``] | 711 | | `KG` | readonly [``"en-GB"``] | 712 | | `KH` | readonly [``"en-GB"``, ``"fr-FR"``] | 713 | | `KN` | readonly [``"en-GB"``] | 714 | | `KR` | readonly [``"ko"``, ``"en-GB"``] | 715 | | `KW` | readonly [``"en-GB"``, ``"ar"``] | 716 | | `KY` | readonly [``"en-GB"``] | 717 | | `KZ` | readonly [``"en-GB"``] | 718 | | `LA` | readonly [``"en-GB"``, ``"fr-FR"``] | 719 | | `LB` | readonly [``"en-GB"``, ``"fr-FR"``, ``"ar"``] | 720 | | `LC` | readonly [``"en-GB"``] | 721 | | `LK` | readonly [``"en-GB"``] | 722 | | `LR` | readonly [``"en-GB"``] | 723 | | `LT` | readonly [``"en-GB"``] | 724 | | `LU` | readonly [``"en-GB"``, ``"fr-FR"``, ``"de-DE"``] | 725 | | `LV` | readonly [``"en-GB"``] | 726 | | `LY` | readonly [``"en-GB"``, ``"ar"``] | 727 | | `MA` | readonly [``"en-GB"``, ``"fr-FR"``, ``"ar"``] | 728 | | `MD` | readonly [``"en-GB"``] | 729 | | `ME` | readonly [``"en-GB"``, ``"hr"``] | 730 | | `MG` | readonly [``"en-GB"``, ``"fr-FR"``] | 731 | | `MK` | readonly [``"en-GB"``] | 732 | | `ML` | readonly [``"en-GB"``, ``"fr-FR"``] | 733 | | `MM` | readonly [``"en-GB"``] | 734 | | `MN` | readonly [``"en-GB"``] | 735 | | `MO` | readonly [``"zh-Hant-HK"``, ``"en-GB"``, ``"zh-Hant-TW"``] | 736 | | `MR` | readonly [``"en-GB"``, ``"fr-FR"``, ``"ar"``] | 737 | | `MS` | readonly [``"en-GB"``] | 738 | | `MT` | readonly [``"en-GB"``] | 739 | | `MU` | readonly [``"en-GB"``, ``"fr-FR"``] | 740 | | `MV` | readonly [``"en-GB"``] | 741 | | `MW` | readonly [``"en-GB"``] | 742 | | `MX` | readonly [``"es-MX"``, ``"en-GB"``] | 743 | | `MY` | readonly [``"en-GB"``, ``"ms"``] | 744 | | `MZ` | readonly [``"en-GB"``] | 745 | | `NA` | readonly [``"en-GB"``] | 746 | | `NE` | readonly [``"en-GB"``, ``"fr-FR"``] | 747 | | `NG` | readonly [``"en-GB"``] | 748 | | `NI` | readonly [``"es-MX"``, ``"en-GB"``] | 749 | | `NL` | readonly [``"nl"``, ``"en-GB"``] | 750 | | `NO` | readonly [``"en-GB"``, ``"nb"``] | 751 | | `NP` | readonly [``"en-GB"``] | 752 | | `NR` | readonly [``"en-GB"``] | 753 | | `NZ` | readonly [``"en-AU"``, ``"en-GB"``] | 754 | | `OM` | readonly [``"en-GB"``, ``"ar"``] | 755 | | `PA` | readonly [``"es-MX"``, ``"en-GB"``] | 756 | | `PE` | readonly [``"es-MX"``, ``"en-GB"``] | 757 | | `PG` | readonly [``"en-GB"``] | 758 | | `PH` | readonly [``"en-GB"``] | 759 | | `PK` | readonly [``"en-GB"``] | 760 | | `PL` | readonly [``"en-GB"``, ``"pl"``] | 761 | | `PT` | readonly [``"pt-PT"``, ``"en-GB"``] | 762 | | `PW` | readonly [``"en-GB"``] | 763 | | `PY` | readonly [``"es-MX"``, ``"en-GB"``] | 764 | | `QA` | readonly [``"en-GB"``, ``"ar"``] | 765 | | `RO` | readonly [``"en-GB"``, ``"ro"``] | 766 | | `RS` | readonly [``"en-GB"``, ``"hr"``] | 767 | | `RU` | readonly [``"ru"``, ``"en-GB"``, ``"uk"``] | 768 | | `RW` | readonly [``"en-GB"``, ``"fr-FR"``] | 769 | | `SA` | readonly [``"en-GB"``, ``"ar"``] | 770 | | `SB` | readonly [``"en-GB"``] | 771 | | `SC` | readonly [``"en-GB"``, ``"fr-FR"``] | 772 | | `SE` | readonly [``"sv"``, ``"en-GB"``] | 773 | | `SG` | readonly [``"en-GB"``, ``"zh-Hans-CN"``] | 774 | | `SI` | readonly [``"en-GB"``] | 775 | | `SK` | readonly [``"en-GB"``, ``"sk"``] | 776 | | `SL` | readonly [``"en-GB"``] | 777 | | `SN` | readonly [``"en-GB"``, ``"fr-FR"``] | 778 | | `SR` | readonly [``"en-GB"``, ``"nl"``] | 779 | | `ST` | readonly [``"en-GB"``] | 780 | | `SV` | readonly [``"es-MX"``, ``"en-GB"``] | 781 | | `SZ` | readonly [``"en-GB"``] | 782 | | `TC` | readonly [``"en-GB"``] | 783 | | `TD` | readonly [``"en-GB"``, ``"fr-FR"``] | 784 | | `TH` | readonly [``"en-GB"``, ``"th"``] | 785 | | `TJ` | readonly [``"en-GB"``] | 786 | | `TM` | readonly [``"en-GB"``] | 787 | | `TN` | readonly [``"en-GB"``, ``"fr-FR"``, ``"ar"``] | 788 | | `TO` | readonly [``"en-GB"``] | 789 | | `TR` | readonly [``"en-GB"``, ``"tr"``] | 790 | | `TT` | readonly [``"en-GB"``, ``"fr-FR"``] | 791 | | `TW` | readonly [``"zh-Hant-TW"``, ``"en-GB"``] | 792 | | `TZ` | readonly [``"en-GB"``] | 793 | | `UA` | readonly [``"en-GB"``, ``"uk"``, ``"ru"``] | 794 | | `UG` | readonly [``"en-GB"``] | 795 | | `US` | readonly [``"en-US"``, ``"es-MX"``, ``"ar"``, ``"ru"``, ``"zh-Hans-CN"``, ``"fr-FR"``, ``"ko"``, ``"pt-BR"``, ``"vi"``, ``"zh-Hant-TW"``] | 796 | | `UY` | readonly [``"en-GB"``, ``"es-MX"``] | 797 | | `UZ` | readonly [``"en-GB"``] | 798 | | `VC` | readonly [``"en-GB"``] | 799 | | `VE` | readonly [``"es-MX"``, ``"en-GB"``] | 800 | | `VG` | readonly [``"en-GB"``] | 801 | | `VN` | readonly [``"en-GB"``, ``"vi"``] | 802 | | `VU` | readonly [``"en-GB"``, ``"fr-FR"``] | 803 | | `XK` | readonly [``"en-GB"``] | 804 | | `YE` | readonly [``"en-GB"``, ``"ar"``] | 805 | | `ZA` | readonly [``"en-GB"``] | 806 | | `ZM` | readonly [``"en-GB"``] | 807 | | `ZW` | readonly [``"en-GB"``] | 808 | 809 | #### Defined in 810 | 811 | [common/consts.ts:317](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L317) 812 | 813 | ___ 814 | 815 | ### appDetailsAvailableAttributes 816 | 817 | • `Const` **appDetailsAvailableAttributes**: readonly [``"artistName"``, ``"artwork"``, ``"bundleId"``, ``"chartPositions"``, ``"contentRatingsBySystem"``, ``"copyright"``, ``"customArtwork"``, ``"customScreenshotsByType"``, ``"customVideoPreviewsByType"``, ``"description"``, ``"deviceFamilies"``, ``"editorialArtwork"``, ``"eula"``, ``"externalVersionId"``, ``"familyShareEnabledDate"``, ``"fileSizeByDevice"``, ``"genreDisplayName"``, ``"hasEula"``, ``"hasFamilyShareableInAppPurchases"``, ``"hasInAppPurchases"``, ``"hasMessagesExtension"``, ``"hasPrivacyPolicyText"``, ``"hasSafariExtension"``, ``"is32bitOnly"``, ``"isAppleWatchSupported"``, ``"isDeliveredInIOSAppForWatchOS"``, ``"isFirstPartyHideableApp"``, ``"isGameCenterEnabled"``, ``"isHiddenFromSpringboard"``, ``"isIOSBinaryMacOSCompatible"``, ``"isPreorder"``, ``"isSiriSupported"``, ``"isStandaloneForWatchOS"``, ``"isStandaloneWithCompanionForWatchOS"``, ``"languageList"``, ``"maxPlayers"``, ``"messagesScreenshots"``, ``"minimumMacOSVersion"``, ``"minimumOSVersion"``, ``"minPlayers"``, ``"name"``, ``"offers"``, ``"privacy"``, ``"privacyDetails"``, ``"privacyPolicyText"``, ``"privacyPolicyUrl"``, ``"releaseDate"``, ``"remoteControllerRequirement"``, ``"requiredCapabilities"``, ``"requirementsByDeviceFamily"``, ``"requirementsString"``, ``"requires32bit"``, ``"requiresGameController"``, ``"reviewsRestricted"``, ``"seller"``, ``"sellerLabel"``, ``"supportedLocales"``, ``"supportsArcade"``, ``"supportsFunCamera"``, ``"supportsGameController"``, ``"supportsPassbook"``, ``"supportURLForLanguage"``, ``"url"``, ``"userRating"``, ``"usesLocationBackgroundMode"``, ``"versionHistory"``, ``"websiteUrl"``] 818 | 819 | The attributes (fields) that can be requested from the app details endpoint. 820 | 821 | No publicly available documentation exists for these. In most cases, it is quite obvious what they mean from the name 822 | and/or returned data. 823 | 824 | **`Remarks`** 825 | 826 | Compiled through trial and error and from looking at requests made by the App Store app. 827 | 828 | **`See`** 829 | 830 | [https://github.com/tweaselORG/parse-tunes/issues/6](https://github.com/tweaselORG/parse-tunes/issues/6) 831 | 832 | #### Defined in 833 | 834 | [common/app-meta.ts:14](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/app-meta.ts#L14) 835 | 836 | ___ 837 | 838 | ### appDetailsTokenUrls 839 | 840 | • `Const` **appDetailsTokenUrls**: readonly [``"https://apps.apple.com/404"``, ``"https://apps.apple.com/story/id1538632801"``, ``"https://apps.apple.com/us/app/facebook/id284882215"``] 841 | 842 | List of URLs to pages on the App Store that contain a token for Apple's media API (amp-api.apps.apple.com) in their 843 | response. 844 | 845 | **`Remarks`** 846 | 847 | These are in the order of their response size. We'll try the smallest one first. 848 | 849 | #### Defined in 850 | 851 | [endpoints/app-details.ts:19](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/app-details.ts#L19) 852 | 853 | ___ 854 | 855 | ### charts 856 | 857 | • `Const` **charts**: `Object` 858 | 859 | The App Store top charts that can be fetched. 860 | 861 | **`See`** 862 | 863 | https://github.com/tweaselORG/parse-tunes/issues/2#issuecomment-1377239436 864 | 865 | #### Type declaration 866 | 867 | | Name | Type | 868 | | :------ | :------ | 869 | | `topFreeIpad` | ``44`` | 870 | | `topFreeIphone` | ``27`` | 871 | | `topGrossingIpad` | ``46`` | 872 | | `topGrossingIphone` | ``38`` | 873 | | `topPaidIpad` | ``45`` | 874 | | `topPaidIphone` | ``30`` | 875 | 876 | #### Defined in 877 | 878 | [endpoints/top-charts.ts:9](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/top-charts.ts#L9) 879 | 880 | ___ 881 | 882 | ### countries 883 | 884 | • `Const` **countries**: `Object` 885 | 886 | The countries that can appear as the first parameter for the `X-Apple-Store-Front` header in a request to an iTunes 887 | endpoint. 888 | 889 | **`Remarks`** 890 | 891 | Generated from: 892 | https://web.archive.org/web/20191206001952/https://affiliate.itunes.apple.com/resources/documentation/linking-to-the-itunes-music-store/#appendix 893 | (using [this script](https://github.com/tweaselORG/parse-tunes/issues/1#issuecomment-1377105173)). 894 | 895 | #### Type declaration 896 | 897 | | Name | Type | 898 | | :------ | :------ | 899 | | `AE` | ``143481`` | 900 | | `AG` | ``143540`` | 901 | | `AI` | ``143538`` | 902 | | `AM` | ``143524`` | 903 | | `AO` | ``143564`` | 904 | | `AR` | ``143505`` | 905 | | `AT` | ``143445`` | 906 | | `AU` | ``143460`` | 907 | | `AZ` | ``143568`` | 908 | | `BB` | ``143541`` | 909 | | `BD` | ``143490`` | 910 | | `BE` | ``143446`` | 911 | | `BG` | ``143526`` | 912 | | `BH` | ``143559`` | 913 | | `BM` | ``143542`` | 914 | | `BN` | ``143560`` | 915 | | `BO` | ``143556`` | 916 | | `BR` | ``143503`` | 917 | | `BS` | ``143539`` | 918 | | `BW` | ``143525`` | 919 | | `BY` | ``143565`` | 920 | | `BZ` | ``143555`` | 921 | | `CA` | ``143455`` | 922 | | `CH` | ``143459`` | 923 | | `CI` | ``143527`` | 924 | | `CL` | ``143483`` | 925 | | `CN` | ``143465`` | 926 | | `CO` | ``143501`` | 927 | | `CR` | ``143495`` | 928 | | `CY` | ``143557`` | 929 | | `CZ` | ``143489`` | 930 | | `DE` | ``143443`` | 931 | | `DK` | ``143458`` | 932 | | `DM` | ``143545`` | 933 | | `DO` | ``143508`` | 934 | | `DZ` | ``143563`` | 935 | | `EC` | ``143509`` | 936 | | `EE` | ``143518`` | 937 | | `EG` | ``143516`` | 938 | | `ES` | ``143454`` | 939 | | `FI` | ``143447`` | 940 | | `FR` | ``143442`` | 941 | | `GB` | ``143444`` | 942 | | `GD` | ``143546`` | 943 | | `GH` | ``143573`` | 944 | | `GR` | ``143448`` | 945 | | `GT` | ``143504`` | 946 | | `GY` | ``143553`` | 947 | | `HK` | ``143463`` | 948 | | `HN` | ``143510`` | 949 | | `HR` | ``143494`` | 950 | | `HU` | ``143482`` | 951 | | `ID` | ``143476`` | 952 | | `IE` | ``143449`` | 953 | | `IL` | ``143491`` | 954 | | `IN` | ``143467`` | 955 | | `IS` | ``143558`` | 956 | | `IT` | ``143450`` | 957 | | `JM` | ``143511`` | 958 | | `JO` | ``143528`` | 959 | | `JP` | ``143462`` | 960 | | `KE` | ``143529`` | 961 | | `KN` | ``143548`` | 962 | | `KR` | ``143466`` | 963 | | `KW` | ``143493`` | 964 | | `KY` | ``143544`` | 965 | | `KZ` | ``143517`` | 966 | | `LB` | ``143497`` | 967 | | `LC` | ``143549`` | 968 | | `LI` | ``143522`` | 969 | | `LK` | ``143486`` | 970 | | `LT` | ``143520`` | 971 | | `LU` | ``143451`` | 972 | | `LV` | ``143519`` | 973 | | `MD` | ``143523`` | 974 | | `MG` | ``143531`` | 975 | | `MK` | ``143530`` | 976 | | `ML` | ``143532`` | 977 | | `MO` | ``143515`` | 978 | | `MS` | ``143547`` | 979 | | `MT` | ``143521`` | 980 | | `MU` | ``143533`` | 981 | | `MV` | ``143488`` | 982 | | `MX` | ``143468`` | 983 | | `MY` | ``143473`` | 984 | | `NE` | ``143534`` | 985 | | `NG` | ``143561`` | 986 | | `NI` | ``143512`` | 987 | | `NL` | ``143452`` | 988 | | `NO` | ``143457`` | 989 | | `NP` | ``143484`` | 990 | | `NZ` | ``143461`` | 991 | | `OM` | ``143562`` | 992 | | `PA` | ``143485`` | 993 | | `PE` | ``143507`` | 994 | | `PH` | ``143474`` | 995 | | `PK` | ``143477`` | 996 | | `PL` | ``143478`` | 997 | | `PT` | ``143453`` | 998 | | `PY` | ``143513`` | 999 | | `QA` | ``143498`` | 1000 | | `RO` | ``143487`` | 1001 | | `RS` | ``143500`` | 1002 | | `RU` | ``143469`` | 1003 | | `SA` | ``143479`` | 1004 | | `SE` | ``143456`` | 1005 | | `SG` | ``143464`` | 1006 | | `SI` | ``143499`` | 1007 | | `SK` | ``143496`` | 1008 | | `SN` | ``143535`` | 1009 | | `SR` | ``143554`` | 1010 | | `SV` | ``143506`` | 1011 | | `TC` | ``143552`` | 1012 | | `TH` | ``143475`` | 1013 | | `TN` | ``143536`` | 1014 | | `TR` | ``143480`` | 1015 | | `TT` | ``143551`` | 1016 | | `TW` | ``143470`` | 1017 | | `TZ` | ``143572`` | 1018 | | `UA` | ``143492`` | 1019 | | `UG` | ``143537`` | 1020 | | `US` | ``143441`` | 1021 | | `UY` | ``143514`` | 1022 | | `UZ` | ``143566`` | 1023 | | `VC` | ``143550`` | 1024 | | `VE` | ``143502`` | 1025 | | `VG` | ``143543`` | 1026 | | `VN` | ``143471`` | 1027 | | `YE` | ``143571`` | 1028 | | `ZA` | ``143472`` | 1029 | 1030 | #### Defined in 1031 | 1032 | [common/consts.ts:10](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L10) 1033 | 1034 | ___ 1035 | 1036 | ### genres 1037 | 1038 | • `Const` **genres**: `Object` 1039 | 1040 | The genres and subgenres of apps on the App Store. 1041 | 1042 | **`Remarks`** 1043 | 1044 | Generated from https://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres (using [this 1045 | script](https://github.com/tweaselORG/parse-tunes/issues/3#issuecomment-1384373531)). 1046 | 1047 | #### Type declaration 1048 | 1049 | | Name | Type | 1050 | | :------ | :------ | 1051 | | `Books` | ``6018`` | 1052 | | `Business` | ``6000`` | 1053 | | `Catalogs` | ``6022`` | 1054 | | `Developer Tools` | ``6026`` | 1055 | | `Education` | ``6017`` | 1056 | | `Entertainment` | ``6016`` | 1057 | | `Finance` | ``6015`` | 1058 | | `Food & Drink` | ``6023`` | 1059 | | `Games` | ``6014`` | 1060 | | `Graphics & Design` | ``6027`` | 1061 | | `Health & Fitness` | ``6013`` | 1062 | | `Lifestyle` | ``6012`` | 1063 | | `Magazines & Newspapers` | ``6021`` | 1064 | | `Medical` | ``6020`` | 1065 | | `Music` | ``6011`` | 1066 | | `Navigation` | ``6010`` | 1067 | | `News` | ``6009`` | 1068 | | `Photo & Video` | ``6008`` | 1069 | | `Productivity` | ``6007`` | 1070 | | `Reference` | ``6006`` | 1071 | | `Shopping` | ``6024`` | 1072 | | `Social Networking` | ``6005`` | 1073 | | `Sports` | ``6004`` | 1074 | | `Stickers` | ``6025`` | 1075 | | `Travel` | ``6003`` | 1076 | | `Utilities` | ``6002`` | 1077 | | `Weather` | ``6001`` | 1078 | | `all` | ``36`` | 1079 | 1080 | #### Defined in 1081 | 1082 | [common/consts.ts:274](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L274) 1083 | 1084 | ___ 1085 | 1086 | ### languages 1087 | 1088 | • `Const` **languages**: `Object` 1089 | 1090 | The languages language that can appear as the second parameter for the `X-Apple-Store-Front` header in a request to 1091 | an iTunes endpoint. 1092 | 1093 | Note: Not all combinations between country and language are possible. A list of possible combinations can be obtained 1094 | from this Apple Music endpoint: https://api.music.apple.com/v1/storefronts. If no language is included in the header, 1095 | a sensible default is used (also listed in the API response). 1096 | 1097 | **`Remarks`** 1098 | 1099 | Adapted after: https://stackoverflow.com/a/58776183/3211062. 1100 | 1101 | **`Todo`** 1102 | 1103 | Is this list complete? Can we find a better source? 1104 | ([#1](https://github.com/tweaselORG/parse-tunes/issues/1#issuecomment-1384047420)) 1105 | 1106 | #### Type declaration 1107 | 1108 | | Name | Type | 1109 | | :------ | :------ | 1110 | | `ca-ES` | ``42`` | 1111 | | `cs-CZ` | ``22`` | 1112 | | `da-DK` | ``11`` | 1113 | | `de-CH` | ``57`` | 1114 | | `de-DE` | ``4`` | 1115 | | `el-GR` | ``23`` | 1116 | | `en-AU` | ``27`` | 1117 | | `en-CA` | ``6`` | 1118 | | `en-GB` | ``2`` | 1119 | | `en-US` | ``1`` | 1120 | | `es-ES` | ``8`` | 1121 | | `es-MX` | ``28`` | 1122 | | `fi-FI` | ``12`` | 1123 | | `fr-CA` | ``5`` | 1124 | | `fr-FR` | ``3`` | 1125 | | `hi-IN` | ``50`` | 1126 | | `hr-HR` | ``41`` | 1127 | | `hu-HU` | ``21`` | 1128 | | `id-ID` | ``37`` | 1129 | | `it-IT` | ``7`` | 1130 | | `ja-JP` | ``9`` | 1131 | | `ko-KR` | ``13`` | 1132 | | `ms-MY` | ``38`` | 1133 | | `nl-NL` | ``10`` | 1134 | | `no-NO` | ``14`` | 1135 | | `pl-PL` | ``20`` | 1136 | | `pt-BR` | ``15`` | 1137 | | `pt-PT` | ``24`` | 1138 | | `ro-RO` | ``39`` | 1139 | | `ru-RU` | ``16`` | 1140 | | `sk-SK` | ``40`` | 1141 | | `sv-SE` | ``17`` | 1142 | | `th-TH` | ``35`` | 1143 | | `tr-TR` | ``25`` | 1144 | | `uk-UA` | ``29`` | 1145 | | `vi-VI` | ``43`` | 1146 | | `zh-CN` | ``19`` | 1147 | | `zh-HK` | ``45`` | 1148 | | `zh-TW` | ``18`` | 1149 | 1150 | #### Defined in 1151 | 1152 | [common/consts.ts:167](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L167) 1153 | 1154 | ___ 1155 | 1156 | ### platforms 1157 | 1158 | • `Const` **platforms**: `Object` 1159 | 1160 | The platforms that can appear as the third parameter for the `X-Apple-Store-Front` header in a request to an iTunes 1161 | endpoint. The list is not complete. 1162 | 1163 | From experimentation, `K8`, `P8`, `P84`, and `K84` always have a JSON response with the desired data. The others 1164 | return UI markup as HTML or XML (PLIST), some don't even include the desired data in the response. 1165 | 1166 | **`Remarks`** 1167 | 1168 | Adapted after: https://gist.github.com/sgmurphy/1878352?permalink_comment_id=2977743#gistcomment-2977743. 1169 | 1170 | **`Todo`** 1171 | 1172 | Is this list complete? Can we find a better source? 1173 | ([#1](https://github.com/tweaselORG/parse-tunes/issues/1#issuecomment-1384068713)) 1174 | 1175 | #### Type declaration 1176 | 1177 | | Name | Type | 1178 | | :------ | :------ | 1179 | | `Configurator` | ``34`` | 1180 | | `EnterpriseStore` | ``14`` | 1181 | | `K6` | ``15`` | 1182 | | `K7` | ``20`` | 1183 | | `K71` | ``23`` | 1184 | | `K8` | ``25`` | 1185 | | `K84` | ``30`` | 1186 | | `Mac1` | ``42`` | 1187 | | `MacAMPLibrary1` | ``40`` | 1188 | | `MacMusic1` | ``39`` | 1189 | | `MacPodcasts1` | ``38`` | 1190 | | `MacTV1` | ``41`` | 1191 | | `P6` | ``16`` | 1192 | | `P7` | ``21`` | 1193 | | `P71` | ``24`` | 1194 | | `P8` | ``26`` | 1195 | | `P84` | ``29`` | 1196 | | `VolumeStore` | ``11`` | 1197 | | `iTunes10` | ``12`` | 1198 | | `iTunes11` | ``17`` | 1199 | | `iTunes12` | ``28`` | 1200 | | `iTunes122` | ``32`` | 1201 | 1202 | #### Defined in 1203 | 1204 | [common/consts.ts:232](https://github.com/tweaselORG/parse-tunes/blob/main/src/common/consts.ts#L232) 1205 | 1206 | ## Functions 1207 | 1208 | ### fetchAppDetails 1209 | 1210 | ▸ **fetchAppDetails**<`Country`, `Platforms`, `Attributes`\>(`request`): `Promise`<[`AppDetailsResponse`](README.md#appdetailsresponse)<[`AppDetailsPlatformInResponseForRequest`](README.md#appdetailsplatforminresponseforrequest)[`Platforms`[`number`]], `Attributes`[`number`]\>\> 1211 | 1212 | Fetch the details for an app from the App Store. You can request a lot of different information about the app. The 1213 | `attributes` parameter specifies which attributes to fetch. See [appDetailsAvailableAttributes](README.md#appdetailsavailableattributes) for a list of 1214 | all available attributes. 1215 | 1216 | #### Type parameters 1217 | 1218 | | Name | Type | 1219 | | :------ | :------ | 1220 | | `Country` | extends ``"DZ"`` \| ``"AO"`` \| ``"AI"`` \| ``"AG"`` \| ``"AR"`` \| ``"AM"`` \| ``"AU"`` \| ``"AT"`` \| ``"AZ"`` \| ``"BH"`` \| ``"BB"`` \| ``"BY"`` \| ``"BE"`` \| ``"BZ"`` \| ``"BM"`` \| ``"BO"`` \| ``"BW"`` \| ``"BR"`` \| ``"VG"`` \| ``"BN"`` \| ``"BG"`` \| ``"CA"`` \| ``"KY"`` \| ``"CL"`` \| ``"CN"`` \| ``"CO"`` \| ``"CR"`` \| ``"CI"`` \| ``"HR"`` \| ``"CY"`` \| ``"CZ"`` \| ``"DK"`` \| ``"DM"`` \| ``"DO"`` \| ``"EC"`` \| ``"EG"`` \| ``"SV"`` \| ``"EE"`` \| ``"FI"`` \| ``"FR"`` \| ``"DE"`` \| ``"GH"`` \| ``"GR"`` \| ``"GD"`` \| ``"GT"`` \| ``"GY"`` \| ``"HN"`` \| ``"HK"`` \| ``"HU"`` \| ``"IS"`` \| ``"IN"`` \| ``"ID"`` \| ``"IE"`` \| ``"IL"`` \| ``"IT"`` \| ``"JM"`` \| ``"JP"`` \| ``"JO"`` \| ``"KZ"`` \| ``"KE"`` \| ``"KR"`` \| ``"KW"`` \| ``"LV"`` \| ``"LB"`` \| ``"LT"`` \| ``"LU"`` \| ``"MO"`` \| ``"MK"`` \| ``"MG"`` \| ``"MY"`` \| ``"MV"`` \| ``"ML"`` \| ``"MT"`` \| ``"MU"`` \| ``"MX"`` \| ``"MD"`` \| ``"MS"`` \| ``"NP"`` \| ``"NL"`` \| ``"NZ"`` \| ``"NI"`` \| ``"NE"`` \| ``"NG"`` \| ``"NO"`` \| ``"OM"`` \| ``"PK"`` \| ``"PA"`` \| ``"PY"`` \| ``"PE"`` \| ``"PH"`` \| ``"PL"`` \| ``"PT"`` \| ``"QA"`` \| ``"RO"`` \| ``"RU"`` \| ``"SA"`` \| ``"SN"`` \| ``"RS"`` \| ``"SG"`` \| ``"SK"`` \| ``"SI"`` \| ``"ZA"`` \| ``"ES"`` \| ``"LK"`` \| ``"KN"`` \| ``"LC"`` \| ``"VC"`` \| ``"SR"`` \| ``"SE"`` \| ``"CH"`` \| ``"TW"`` \| ``"TZ"`` \| ``"TH"`` \| ``"BS"`` \| ``"TT"`` \| ``"TN"`` \| ``"TR"`` \| ``"TC"`` \| ``"UG"`` \| ``"GB"`` \| ``"UA"`` \| ``"AE"`` \| ``"UY"`` \| ``"US"`` \| ``"UZ"`` \| ``"VE"`` \| ``"VN"`` \| ``"YE"`` \| ``"AF"`` \| ``"AL"`` \| ``"BJ"`` \| ``"BT"`` \| ``"BA"`` \| ``"BF"`` \| ``"KH"`` \| ``"CM"`` \| ``"CV"`` \| ``"TD"`` \| ``"CD"`` \| ``"SZ"`` \| ``"FJ"`` \| ``"GA"`` \| ``"GM"`` \| ``"GE"`` \| ``"GW"`` \| ``"IQ"`` \| ``"XK"`` \| ``"KG"`` \| ``"LA"`` \| ``"LR"`` \| ``"LY"`` \| ``"MW"`` \| ``"MR"`` \| ``"FM"`` \| ``"MN"`` \| ``"ME"`` \| ``"MA"`` \| ``"MZ"`` \| ``"MM"`` \| ``"NA"`` \| ``"NR"`` \| ``"PW"`` \| ``"PG"`` \| ``"CG"`` \| ``"RW"`` \| ``"SC"`` \| ``"SL"`` \| ``"SB"`` \| ``"ST"`` \| ``"TJ"`` \| ``"TO"`` \| ``"TM"`` \| ``"VU"`` \| ``"ZM"`` \| ``"ZW"`` | 1221 | | `Platforms` | extends [`AppDetailsPlatformInRequest`](README.md#appdetailsplatforminrequest)[] | 1222 | | `Attributes` | extends (``"artistName"`` \| ``"artwork"`` \| ``"bundleId"`` \| ``"chartPositions"`` \| ``"contentRatingsBySystem"`` \| ``"copyright"`` \| ``"customArtwork"`` \| ``"customScreenshotsByType"`` \| ``"customVideoPreviewsByType"`` \| ``"description"`` \| ``"deviceFamilies"`` \| ``"editorialArtwork"`` \| ``"eula"`` \| ``"externalVersionId"`` \| ``"familyShareEnabledDate"`` \| ``"fileSizeByDevice"`` \| ``"genreDisplayName"`` \| ``"hasEula"`` \| ``"hasFamilyShareableInAppPurchases"`` \| ``"hasInAppPurchases"`` \| ``"hasMessagesExtension"`` \| ``"hasPrivacyPolicyText"`` \| ``"hasSafariExtension"`` \| ``"is32bitOnly"`` \| ``"isAppleWatchSupported"`` \| ``"isDeliveredInIOSAppForWatchOS"`` \| ``"isFirstPartyHideableApp"`` \| ``"isGameCenterEnabled"`` \| ``"isHiddenFromSpringboard"`` \| ``"isIOSBinaryMacOSCompatible"`` \| ``"isPreorder"`` \| ``"isSiriSupported"`` \| ``"isStandaloneForWatchOS"`` \| ``"isStandaloneWithCompanionForWatchOS"`` \| ``"languageList"`` \| ``"maxPlayers"`` \| ``"messagesScreenshots"`` \| ``"minimumMacOSVersion"`` \| ``"minimumOSVersion"`` \| ``"minPlayers"`` \| ``"name"`` \| ``"offers"`` \| ``"privacy"`` \| ``"privacyDetails"`` \| ``"privacyPolicyText"`` \| ``"privacyPolicyUrl"`` \| ``"releaseDate"`` \| ``"remoteControllerRequirement"`` \| ``"requiredCapabilities"`` \| ``"requirementsByDeviceFamily"`` \| ``"requirementsString"`` \| ``"requires32bit"`` \| ``"requiresGameController"`` \| ``"reviewsRestricted"`` \| ``"seller"`` \| ``"sellerLabel"`` \| ``"supportedLocales"`` \| ``"supportsArcade"`` \| ``"supportsFunCamera"`` \| ``"supportsGameController"`` \| ``"supportsPassbook"`` \| ``"supportURLForLanguage"`` \| ``"url"`` \| ``"userRating"`` \| ``"usesLocationBackgroundMode"`` \| ``"versionHistory"`` \| ``"websiteUrl"``)[] | 1223 | 1224 | #### Parameters 1225 | 1226 | | Name | Type | Description | 1227 | | :------ | :------ | :------ | 1228 | | `request` | [`AppDetailsRequest`](README.md#appdetailsrequest)<`Country`, `Platforms`, `Attributes`\> | The request parameters. | 1229 | 1230 | #### Returns 1231 | 1232 | `Promise`<[`AppDetailsResponse`](README.md#appdetailsresponse)<[`AppDetailsPlatformInResponseForRequest`](README.md#appdetailsplatforminresponseforrequest)[`Platforms`[`number`]], `Attributes`[`number`]\>\> 1233 | 1234 | The app details, typed according to the attributes you specified. 1235 | 1236 | #### Defined in 1237 | 1238 | [endpoints/app-details.ts:122](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/app-details.ts#L122) 1239 | 1240 | ___ 1241 | 1242 | ### fetchMediaApiToken 1243 | 1244 | ▸ **fetchMediaApiToken**(): `Promise`<`string`\> 1245 | 1246 | Fetch a token for Apple's media API (amp-api.apps.apple.com), to be used with the [fetchAppDetails](README.md#fetchappdetails) function. 1247 | The token can be used many times (until it expires). 1248 | 1249 | **`Remarks`** 1250 | 1251 | The token is extracted from the HTML of an App Store page (see: https://github.com/tweaselORG/parse-tunes/issues/6). 1252 | 1253 | The token appears to be the same for everyone, and changes from time to time (around every four months). It is a JWT, 1254 | which you can parse to get the expiration date. 1255 | 1256 | #### Returns 1257 | 1258 | `Promise`<`string`\> 1259 | 1260 | The token. 1261 | 1262 | #### Defined in 1263 | 1264 | [endpoints/app-details.ts:36](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/app-details.ts#L36) 1265 | 1266 | ___ 1267 | 1268 | ### fetchTopApps 1269 | 1270 | ▸ **fetchTopApps**(`request`): `Promise`<[`TopChartResult`](README.md#topchartresult)\> 1271 | 1272 | Fetch the app IDs of the top apps in a given top chart. 1273 | 1274 | #### Parameters 1275 | 1276 | | Name | Type | Description | 1277 | | :------ | :------ | :------ | 1278 | | `request` | [`TopChartRequest`](README.md#topchartrequest) | The parameters for which top chart to fetch. | 1279 | 1280 | #### Returns 1281 | 1282 | `Promise`<[`TopChartResult`](README.md#topchartresult)\> 1283 | 1284 | A list of numerical app IDs in the requested top chart. The list is sorted by rank. Currently always has 200 1285 | items. 1286 | 1287 | #### Defined in 1288 | 1289 | [endpoints/top-charts.ts:44](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/top-charts.ts#L44) 1290 | 1291 | ___ 1292 | 1293 | ### searchApps 1294 | 1295 | ▸ **searchApps**<`Country`, `Platforms`\>(`request`): `Promise`<[`AppSearchResponse`](README.md#appsearchresponse)<[`AppDetailsPlatformInResponseForRequest`](README.md#appdetailsplatforminresponseforrequest)[`Platforms`[`number`]]\>\> 1296 | 1297 | Search for apps on the the App Store. You can request a lot of different information about the app. The `attributes` 1298 | parameter specifies which attributes to fetch. See [appDetailsAvailableAttributes](README.md#appdetailsavailableattributes) for a list of all available 1299 | attributes. 1300 | 1301 | #### Type parameters 1302 | 1303 | | Name | Type | 1304 | | :------ | :------ | 1305 | | `Country` | extends ``"DZ"`` \| ``"AO"`` \| ``"AI"`` \| ``"AG"`` \| ``"AR"`` \| ``"AM"`` \| ``"AU"`` \| ``"AT"`` \| ``"AZ"`` \| ``"BH"`` \| ``"BB"`` \| ``"BY"`` \| ``"BE"`` \| ``"BZ"`` \| ``"BM"`` \| ``"BO"`` \| ``"BW"`` \| ``"BR"`` \| ``"VG"`` \| ``"BN"`` \| ``"BG"`` \| ``"CA"`` \| ``"KY"`` \| ``"CL"`` \| ``"CN"`` \| ``"CO"`` \| ``"CR"`` \| ``"CI"`` \| ``"HR"`` \| ``"CY"`` \| ``"CZ"`` \| ``"DK"`` \| ``"DM"`` \| ``"DO"`` \| ``"EC"`` \| ``"EG"`` \| ``"SV"`` \| ``"EE"`` \| ``"FI"`` \| ``"FR"`` \| ``"DE"`` \| ``"GH"`` \| ``"GR"`` \| ``"GD"`` \| ``"GT"`` \| ``"GY"`` \| ``"HN"`` \| ``"HK"`` \| ``"HU"`` \| ``"IS"`` \| ``"IN"`` \| ``"ID"`` \| ``"IE"`` \| ``"IL"`` \| ``"IT"`` \| ``"JM"`` \| ``"JP"`` \| ``"JO"`` \| ``"KZ"`` \| ``"KE"`` \| ``"KR"`` \| ``"KW"`` \| ``"LV"`` \| ``"LB"`` \| ``"LT"`` \| ``"LU"`` \| ``"MO"`` \| ``"MK"`` \| ``"MG"`` \| ``"MY"`` \| ``"MV"`` \| ``"ML"`` \| ``"MT"`` \| ``"MU"`` \| ``"MX"`` \| ``"MD"`` \| ``"MS"`` \| ``"NP"`` \| ``"NL"`` \| ``"NZ"`` \| ``"NI"`` \| ``"NE"`` \| ``"NG"`` \| ``"NO"`` \| ``"OM"`` \| ``"PK"`` \| ``"PA"`` \| ``"PY"`` \| ``"PE"`` \| ``"PH"`` \| ``"PL"`` \| ``"PT"`` \| ``"QA"`` \| ``"RO"`` \| ``"RU"`` \| ``"SA"`` \| ``"SN"`` \| ``"RS"`` \| ``"SG"`` \| ``"SK"`` \| ``"SI"`` \| ``"ZA"`` \| ``"ES"`` \| ``"LK"`` \| ``"KN"`` \| ``"LC"`` \| ``"VC"`` \| ``"SR"`` \| ``"SE"`` \| ``"CH"`` \| ``"TW"`` \| ``"TZ"`` \| ``"TH"`` \| ``"BS"`` \| ``"TT"`` \| ``"TN"`` \| ``"TR"`` \| ``"TC"`` \| ``"UG"`` \| ``"GB"`` \| ``"UA"`` \| ``"AE"`` \| ``"UY"`` \| ``"US"`` \| ``"UZ"`` \| ``"VE"`` \| ``"VN"`` \| ``"YE"`` \| ``"AF"`` \| ``"AL"`` \| ``"BJ"`` \| ``"BT"`` \| ``"BA"`` \| ``"BF"`` \| ``"KH"`` \| ``"CM"`` \| ``"CV"`` \| ``"TD"`` \| ``"CD"`` \| ``"SZ"`` \| ``"FJ"`` \| ``"GA"`` \| ``"GM"`` \| ``"GE"`` \| ``"GW"`` \| ``"IQ"`` \| ``"XK"`` \| ``"KG"`` \| ``"LA"`` \| ``"LR"`` \| ``"LY"`` \| ``"MW"`` \| ``"MR"`` \| ``"FM"`` \| ``"MN"`` \| ``"ME"`` \| ``"MA"`` \| ``"MZ"`` \| ``"MM"`` \| ``"NA"`` \| ``"NR"`` \| ``"PW"`` \| ``"PG"`` \| ``"CG"`` \| ``"RW"`` \| ``"SC"`` \| ``"SL"`` \| ``"SB"`` \| ``"ST"`` \| ``"TJ"`` \| ``"TO"`` \| ``"TM"`` \| ``"VU"`` \| ``"ZM"`` \| ``"ZW"`` | 1306 | | `Platforms` | extends [`AppDetailsPlatformInRequest`](README.md#appdetailsplatforminrequest)[] | 1307 | 1308 | #### Parameters 1309 | 1310 | | Name | Type | Description | 1311 | | :------ | :------ | :------ | 1312 | | `request` | [`AppSearchRequest`](README.md#appsearchrequest)<`Country`, `Platforms`\> | The request parameters. | 1313 | 1314 | #### Returns 1315 | 1316 | `Promise`<[`AppSearchResponse`](README.md#appsearchresponse)<[`AppDetailsPlatformInResponseForRequest`](README.md#appdetailsplatforminresponseforrequest)[`Platforms`[`number`]]\>\> 1317 | 1318 | The app details, typed according to the attributes you specified. 1319 | 1320 | #### Defined in 1321 | 1322 | [endpoints/search.ts:112](https://github.com/tweaselORG/parse-tunes/blob/main/src/endpoints/search.ts#L112) 1323 | --------------------------------------------------------------------------------