{"id":19156852,"url":"https://github.com/bertrandmartel/tableau-scraping","last_synced_at":"2025-08-29T16:03:57.418Z","repository":{"id":47346663,"uuid":"302487529","full_name":"bertrandmartel/tableau-scraping","owner":"bertrandmartel","description":"Tableau scraper python library. R and Python scripts to scrape data from Tableau viz","archived":false,"fork":false,"pushed_at":"2024-05-08T05:15:09.000Z","size":497,"stargazers_count":135,"open_issues_count":23,"forks_count":22,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-06-25T11:01:11.278Z","etag":null,"topics":["dataframe","pandas","python","r","tableau","web-scraping"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bertrandmartel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-08T23:52:02.000Z","updated_at":"2025-06-10T18:16:19.000Z","dependencies_parsed_at":"2024-06-19T05:18:13.807Z","dependency_job_id":"59465fdd-5db6-4a08-8138-06f6d75017b4","html_url":"https://github.com/bertrandmartel/tableau-scraping","commit_stats":{"total_commits":169,"total_committers":1,"mean_commits":169.0,"dds":0.0,"last_synced_commit":"2762a92641a57a96aba81b20b5b5c600a5ec514e"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/bertrandmartel/tableau-scraping","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Ftableau-scraping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Ftableau-scraping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Ftableau-scraping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Ftableau-scraping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bertrandmartel","download_url":"https://codeload.github.com/bertrandmartel/tableau-scraping/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Ftableau-scraping/sbom","scorecard":{"id":234660,"data":{"date":"2025-08-11","repo":{"name":"github.com/bertrandmartel/tableau-scraping","commit":"2762a92641a57a96aba81b20b5b5c600a5ec514e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.1,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/bertrandmartel/tableau-scraping/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/bertrandmartel/tableau-scraping/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/bertrandmartel/tableau-scraping/ci.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:21","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:22","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2020-73","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: GHSA-9wx4-h78v-vm56","Warn: Project is vulnerable to: PYSEC-2023-74 / GHSA-j8r2-6x86-q33q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T05:24:52.706Z","repository_id":47346663,"created_at":"2025-08-17T05:24:52.706Z","updated_at":"2025-08-17T05:24:52.706Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272717014,"owners_count":24981480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-29T02:00:10.610Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dataframe","pandas","python","r","tableau","web-scraping"],"created_at":"2024-11-09T08:36:08.011Z","updated_at":"2025-08-29T16:03:57.328Z","avatar_url":"https://github.com/bertrandmartel.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tableau Scraper\n\n[![PyPI](https://img.shields.io/pypi/v/TableauScraper.svg)](https://pypi.python.org/pypi/TableauScraper)\n[![CI](https://github.com/bertrandmartel/tableau-scraping/workflows/CI/badge.svg)](https://github.com/bertrandmartel/tableau-scraping/actions)\n[![codecov](https://codecov.io/gh/bertrandmartel/tableau-scraping/branch/master/graph/badge.svg?token=F4R3NZF796)](https://codecov.io/gh/bertrandmartel/tableau-scraping)\n[![License](http://img.shields.io/:license-mit-blue.svg)](LICENSE.md)\n\nPython library to scrape data from [Tableau viz](https://public.tableau.com/fr-fr/gallery)\n\nR library is under development but a script is available to get the worksheets, see [this](https://github.com/bertrandmartel/tableau-scraping#r)\n\n## Python\n\n### Install\n\n```bash\npip install TableauScraper\n```\n\n### Usage\n\n#### Get worksheets data\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = \"https://public.tableau.com/views/PlayerStats-Top5Leagues20192020/OnePlayerSummary\"\n\nts = TS()\nts.loads(url)\nworkbook = ts.getWorkbook()\n\nfor t in workbook.worksheets:\n    print(f\"worksheet name : {t.name}\") #show worksheet name\n    print(t.data) #show dataframe for this worksheet\n```\n\n[Try this on repl.it](https://repl.it/@bertrandmartel/TableauGetWorksheets)\n\n#### Get a specific worksheet\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = \"https://public.tableau.com/views/PlayerStats-Top5Leagues20192020/OnePlayerSummary\"\n\nts = TS()\nts.loads(url)\n\nws = ts.getWorksheet(\"ATT MID CREATIVE COMP\")\nprint(ws.data)\n```\n\n#### select a selectable item\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = \"https://public.tableau.com/views/PlayerStats-Top5Leagues20192020/OnePlayerSummary\"\n\nts = TS()\nts.loads(url)\n\nws = ts.getWorksheet(\"ATT MID CREATIVE COMP\")\n\n# show selectable values\nselections = ws.getSelectableItems()\nprint(selections)\n\n# select that value\ndashboard = ws.select(\"ATTR(Player)\", \"Vinicius Júnior\")\n\n# display worksheets\nfor t in dashboard.worksheets:\n    print(t.data)\n```\n\n[Try this on repl.it](https://repl.it/@bertrandmartel/TableauSelectItem)\n\n#### set parameter\n\nGet list of parameters with `workbook.getParameters()` and set parameter value using `workbook.setParameter(\"column_name\", \"value\")` :\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = \"https://public.tableau.com/views/PlayerStats-Top5Leagues20192020/OnePlayerSummary\"\n\nts = TS()\nts.loads(url)\nworkbook = ts.getWorkbook()\n\n# show parameters values / column\nparameters = workbook.getParameters()\nprint(parameters)\n\n# set parameters column / value\nworkbook = workbook.setParameter(\"P.League 2\", \"Ligue 1\")\n\n# display worksheets\nfor t in workbook.worksheets:\n    print(t.data)\n```\n\n[Try this on repl.it](https://repl.it/@bertrandmartel/TableauParameter)\n\nIt's possible to override the parameter name used in the API requests using `inputParameter`, which is different from the input name:\n\n```\nwb = wb.setParameter(inputName=None, value=\"Ligue 1\",\n                     inputParameter=\"[Parameters].[P.League (copy)_1642969456470679625]\")\n```\n\n#### set filter\n\nGet list of filters with `worksheet.getFilters` and set filter value using `worksheet.setFilter(\"column_name\", \"value\")`:\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = 'https://public.tableau.com/views/WomenInOlympics/Dashboard1'\nts = TS()\nts.loads(url)\n\n# show original data for worksheet\nws = ts.getWorksheet(\"Bar Chart\")\nprint(ws.data)\n\n# get filters columns and values\nfilters = ws.getFilters()\nprint(filters)\n\n# set filter value\nwb = ws.setFilter('Olympics', 'Winter')\n\n# show the new data for worksheet\ncountyWs = wb.getWorksheet(\"Bar Chart\")\nprint(countyWs.data)\n```\n\n[Try this on repl.it](https://repl.it/@bertrandmartel/TableauFilter)\n\n#### More advanced filtering options\n\n- You can specify `dashboardFilter=True` in order to use `dashboard-categorical-filter` API instead of `categorical-filter-by-index` API ([related](https://github.com/bertrandmartel/tableau-scraping/issues/26))\n- When using `dashboardFilter=True` you can skip the filter value check usin `noCheck=True` ([related](https://github.com/bertrandmartel/tableau-scraping/issues/50))\n\n- You can discard `membershipTarget` property from being sent in `setFilter` using `setFilter('COLUMN','VALUE', membershipTarget=False)` ([related](https://github.com/bertrandmartel/tableau-scraping/issues/29))\n\n- You can specify multiple filters for filters that enable that feature using `setFilter('COLUMN', ['VALUE1','VALUE2'])`\n\n- You can specify a \"filter-delta\" filter type adding the parameter `filterDelta=True` like the following `setFilter('COLUMN','VALUE', filterDelta=True)`. This will discard all filters and add the one corresponding to `['VALUE']` in this case. This is helpful when all or some filters are selected by default, and you want to unselect them. The default behaviour (`filterDelta=False`) is `filter-replace` which sometimes doesn't work when filter multi-selection is possible in the dashboard. [example](https://replit.com/@bertrandmartel/TableauUSCustoms)\n\n- In last recourse, you can use `indexValues` property to directly specify the indices (if there is a bug in the library or anything comes up): `setFilter('COLUMN', [], indexValues=[0,1,2])`\n\n#### Story points\n\nSome Tableau dashboard have storypoints where you can navigate. To list the storypoints and go to a specific storypoints:\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = 'https://public.tableau.com/views/EarthquakeTrendStory2/Finished-Earthquakestory'\nts = TS()\nts.loads(url)\nwb = ts.getWorkbook()\n\nprint(wb.getStoryPoints())\nprint(\"go to specific storypoint\")\nsp = wb.goToStoryPoint(storyPointId=10)\n\nprint(sp.getWorksheetNames())\nprint(sp.getWorksheet(\"Timeline\").data)\n```\n\n[Try this on repl.it](https://replit.com/@bertrandmartel/TableauEarthquakeStorypoint)\n\n#### Level drill Up/Down\n\nOn some graph/table, there is a drill up/down feature used to zoom in or out data like this\n![drill up/down](https://user-images.githubusercontent.com/5183022/123021337-332c4980-d3d4-11eb-8e8c-d19c5b989edb.png)\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = 'https://tableau.azdhs.gov/views/ELRv2testlevelandpeopletested/PeopleTested'\nts = TS()\nts.loads(url)\nwb = ts.getWorkbook()\n\nsheetName = \"P1 - Tests by Day W/ % Positivity (Both) (2)\"\n\ndrillDown1 = wb.getWorksheet(sheetName).levelDrill(drillDown=True, position=1)\ndrillDown2 = drillDown1.getWorksheet(sheetName).levelDrill(drillDown=True, position=1)\ndrillDown3 = drillDown2.getWorksheet(sheetName).levelDrill(drillDown=True, position=1)\n\nprint(drillDown1.getWorksheet(sheetName).data)\nprint(drillDown2.getWorksheet(sheetName).data)\nprint(drillDown3.getWorksheet(sheetName).data)\n```\n\n[Try this on repl.it](https://replit.com/@bertrandmartel/TableauCovid19AzdhsPeopleTested)\n\nThe `position` parameter is default to `0`. It doesn't seem to be present in the json configuration. If the default is not working try incrementing it or checkout the network tabs using Chrome devtools.\n\n#### Download CSV data\n\nFor Tableau URL that have the download feature enabled, you can download full data using:\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = 'https://public.tableau.com/views/WYCOVID-19Dashboard/WyomingCOVID-19CaseDashboard'\nts = TS()\nts.loads(url)\nwb = ts.getWorkbook()\ndata = wb.getCsvData(sheetName='case map')\n\nprint(data)\n```\n\nNote that in some Tableau server, the prefix used in the API url is different. As it's set in the javascript, it must be set manually if it's not the same as public.tableau.com like:\n\n```python\nwb.getCsvData(sheetName='worksheet1', prefix=\"vud\")\n```\n\nThe prefix values, I've encountered are: `vud` and `vudcsv`. The default is `vudcsv`.\n\n[Try this on repl.it](https://replit.com/@bertrandmartel/TableauCovidWyomingCsv)\n\n#### Download Cross Tab data\n\nFor Tableau URL that have the crosstab feature enabled, you can download the crosstab using:\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = \"https://tableau.soa.org/t/soa-public/views/USPostLevelTermMortalityExperienceInteractiveTool/DataTable2\"\n\nts = TS()\nts.loads(url)\nwb = ts.getWorkbook()\n\nwb.setParameter(inputName=\"Count or Amount\", value=\"Amount\")\n\ndata = wb.getCrossTabData(\n    sheetName=\"Data Table 2 - Premium Jump \u0026 PLT Duration\")\n\nprint(data)\n```\n\n#### Go to sheet\n\nGet list of all sheets with subsheets visible or invisible, ability to send a go-to-sheet command (dashboar button) :\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = \"https://public.tableau.com/views/COVID-19VaccineTrackerDashboard_16153822244270/Dosesadministered\"\nts = TS()\nts.loads(url)\nworkbook = ts.getWorkbook()\n\nsheets = workbook.getSheets()\nprint(sheets)\n\nnycAdults = workbook.goToSheet(\"NYC Adults\")\nfor t in nycAdults.worksheets:\n    print(f\"worksheet name : {t.name}\")  # show worksheet name\n    print(t.data)  # show dataframe for this worksheet\n```\n\n#### Render tooltip\n\nGet the tooltip html output when `render-tooltip-server` API is called. This is particularly useful when dealing with [server side rendering dashboard](https://github.com/bertrandmartel/tableau-scraping#server-side-rendering):\n\n```python\nfrom tableauscraper import TableauScraper as TS\n\nurl = \"https://public.tableau.com/views/CMI-2_0/CMI\"\n\nts = TS()\nts.loads(url)\nworkbook = ts.getWorkbook()\nws = workbook.getWorksheet(\"US Map - State - CMI\")\n\ntooltipHtml = ws.renderTooltip(x=387, y=196)\nprint(tooltipHtml)\n```\n\n### Sample usecases\n\n- https://replit.com/@bertrandmartel/TableauOregonCovid\n- https://replit.com/@bertrandmartel/TableauCovidIndia\n- https://replit.com/@bertrandmartel/TableauCovidArizona\n- https://replit.com/@bertrandmartel/TableauIllinoisOpioId\n- https://replit.com/@bertrandmartel/TableauCovidNY\n- https://replit.com/@bertrandmartel/TableauCovidNCDHHS\n- https://replit.com/@bertrandmartel/TableauCovidWisconsin\n- https://replit.com/@bertrandmartel/TableauScrapeNewspaper\n- https://replit.com/@bertrandmartel/TableauStoryPoints\n- https://replit.com/@bertrandmartel/TableauCovidOhio\n- https://replit.com/@bertrandmartel/TableauCovidSouthCarolina\n- https://replit.com/@bertrandmartel/TableauCovidNewHampshire\n- https://replit.com/@bertrandmartel/TableauCovidNewJersey\n- https://replit.com/@bertrandmartel/TableauCovid19Wyoming\n- https://replit.com/@bertrandmartel/TableauCovid19Louisiana\n- https://replit.com/@bertrandmartel/TableauCIESFootball\n- https://replit.com/@bertrandmartel/TableauCovid19TestingCommonsASU\n- https://replit.com/@bertrandmartel/TableauCovid19Tracker\n- https://replit.com/@bertrandmartel/TableauCovid19CbreResidentMigration\n- https://replit.com/@bertrandmartel/TableauEarthquakeStorypoint\n- https://replit.com/@bertrandmartel/TableauCovid19AzdhsPeopleTested\n- https://replit.com/@bertrandmartel/TableauCovidDDCMOPH\n- https://replit.com/@bertrandmartel/TableauUSCustoms\n- https://replit.com/@bertrandmartel/TableauONSDemandaMaxima\n- https://replit.com/@bertrandmartel/TableauCovidAZDHSTests\n\n### Server side rendering\n\nIf the tableau url you're working on is using [server side rendering](https://help.tableau.com/current/server/en-us/browser_rendering.htm), data can't be extracted as is.\n\nYou can checkout if your tableau url is using server side rendering by opening chrome development console / network tab. You would notice the API calls have `renderMode` properties set to `render-mode-server`:\n\n![server side render mode](https://user-images.githubusercontent.com/5183022/135779239-8321d6a2-81b6-4ae9-8606-b20ba36a86ae.png)\n\nServer side rendering means that no data is sent to the browser. Instead, the server is rendering the tableau chart using images only and detects selection using mouse coordinates.\n\nTo extract the data, one thing that has worked with some tableau url was to trigger a specific filter that is not server-side-rendered. You can checkout the network tab on Chrome development console to check if the filter call is using or not server-side rendering or client-side-rendering with `renderMode`:\n\n![client side rendering](https://user-images.githubusercontent.com/5183022/115800868-b7198380-a3db-11eb-95c0-7104f7f0c77c.png)\n\nIf the filter is only using client side rendering, you can list all filters and perform the filter for each value. This technique only works if the tableau data has \"cleared\" the filter by default otherwise the data is already cached when the tableau data is loaded, and since it's using server side rendering you can't access this data\n\nCheckout the following repl.it for examples with tableau url using server side rendering:\n\n- https://replit.com/@bertrandmartel/TableauCIESFootball\n- https://replit.com/@bertrandmartel/TableauCovid19TestingCommonsASU\n\n### Testing Python script\n\nTo discover all worksheets, selectable columns and dropdowns, run `prompt.py` script under `scripts` directory :\n\n```bash\ngit clone git@github.com:bertrandmartel/tableau-scraping.git\ncd tableau-scraping/scripts\n\n#get worksheets data\npython3 prompt.py -get workbook -url \"https://public.tableau.com/views/PlayerStats-Top5Leagues20192020/OnePlayerSummary\"\n\n#select a selectable item\npython3 prompt.py -get select -url \"https://public.tableau.com/views/MKTScoredeisolamentosocial/VisoGeral\"\n\n#set a parameter\npython3 prompt.py -get parameter -url \"https://public.tableau.com/views/COVID-19DailyDashboard_15960160643010/Casesbyneighbourhood\"\n```\n\n### Settings\n\n`TableauScraper` class has the following optional parameters :\n\n| Parameters | default value | description                               |\n| ---------- | ------------- | ----------------------------------------- |\n| logLevel   | logging.INFO  | log level                                 |\n| delayMs    | 500           | minimum delay in millis between api calls |\n\n## R\n\nunder `R` directory :\n\n```R\nRscript tableau.R\n```\n\nR library is under development\n\n## Dependencies\n\n[requirements.txt](https://github.com/bertrandmartel/tableau-scraping/blob/master/requirements.txt)\n\n- pandas\n- requests\n- beautifulsoup4\n\n## Stackoverflow Questions\n\nSee [those stackoverflow posts about this topic](https://stackoverflow.com/search?q=user%3A2614364+tableau+%5Bweb-scraping%5D)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertrandmartel%2Ftableau-scraping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbertrandmartel%2Ftableau-scraping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertrandmartel%2Ftableau-scraping/lists"}